redis-om-python/README.md

307 lines
9.8 KiB
Markdown
Raw Normal View History

2021-10-20 01:50:34 +02:00
<h1 align="center">Redis OM</h1>
2021-10-20 00:06:50 +02:00
<p align="center">
<p align="center">
2021-10-23 02:05:10 +02:00
Objecting mapping, and more, for Redis.
2021-10-20 00:06:50 +02:00
</p>
</p>
2021-10-20 00:06:50 +02:00
---
2021-10-20 00:06:50 +02:00
[![Version][version-svg]][package-url]
[![License][license-image]][license-url]
[![Build Status][ci-svg]][ci-url]
2021-10-23 02:05:10 +02:00
**Redis OM Python** makes it easy to model Redis data in your Python applications.
2021-10-20 01:50:34 +02:00
**Redis OM Python** | [Redis OM Node.js][redis-om-js] | [Redis OM Spring][redis-om-spring] | [Redis OM .NET][redis-om-dotnet]
2021-10-20 00:06:50 +02:00
<details>
<summary><strong>Table of contents</strong></summary>
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
2021-10-23 02:05:10 +02:00
- [💡 Why Redis OM?](#-why-redis-om)
- [Starting Redis](#starting-redis)
- [📇 Modeling your domain (and indexing it!)](#-modeling-your-domain-and-indexing-it)
- [🔎 Querying](#-querying)
- [Why this is important](#why-this-is-important)
- [So how do you get RediSearch and RedisJSON?](#so-how-do-you-get-redisearch-and-redisjson)
- [Why Redis OM?](#why)
- [Getting started](#getting-started)
- [Installation](#installation)
- [Documentation](#documentation)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)
- [License](#license)
2021-10-20 00:06:50 +02:00
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
</details>
2021-10-23 02:05:10 +02:00
## 💡 Why Redis OM?
Redis OM provides high-level abstractions for using Redis in Python, making it easy to model and query your Redis domain objects.
2021-10-20 00:06:50 +02:00
2021-10-23 02:05:10 +02:00
This **preview** release contains the following features:
2021-10-20 00:06:50 +02:00
2021-10-23 02:05:10 +02:00
* Declarative object mapping for Redis objects
* Declarative secondary-index generation
* Fluent APIs for querying Redis
2021-10-20 00:06:50 +02:00
## 🏁 Getting started
### Object Mapping
2021-10-23 02:05:10 +02:00
With Redis OM, you get powerful data modeling, extensible data validation with [Pydantic](pydantic-url), and rich query expressions.
2021-10-22 17:31:08 +02:00
2021-10-25 22:26:40 +02:00
Check out this example of how we'd model customer data with Redis OM. First, we create a `Customer` model:
2021-10-22 17:31:08 +02:00
```python
import datetime
from typing import Optional
from pydantic import EmailStr
from redis_om.model import (
HashModel,
)
class Customer(HashModel):
first_name: str
last_name: str
email: EmailStr
join_date: datetime.date
age: int
bio: Optional[str]
```
2021-10-23 02:05:10 +02:00
**NOTE**: Redis OM uses Python type annotations for data validation. See the _Data Validation_ section of this README for more details.
2021-10-22 17:31:08 +02:00
2021-10-23 02:05:10 +02:00
Now that we have a `Customer` model, let's use it to save customer data to Redis.
First, we create a new `Customer` object:
2021-10-22 17:31:08 +02:00
```python
andrew = Customer(
first_name="Andrew",
last_name="Brookins",
email="andrew.brookins@example.com",
join_date=datetime.date.today(),
age=38,
bio="Python developer, works at Redis, Inc."
)
2021-10-23 02:05:10 +02:00
```
The model generates a globally unique primary key automatically without needing to talk to Redis.
2021-10-22 17:31:08 +02:00
2021-10-23 02:05:10 +02:00
```python
2021-10-22 17:31:08 +02:00
print(andrew.pk)
2021-10-23 02:05:10 +02:00
'01FJM6PH661HCNNRC884H6K30C'
```
We can save the model to Redis by calling `save()`:
2021-10-22 17:31:08 +02:00
2021-10-23 02:05:10 +02:00
```python
2021-10-22 17:31:08 +02:00
andrew.save()
2021-10-23 02:05:10 +02:00
```
To retrieve this customer with its primary key, we use `Customer.get()`:
2021-10-22 17:31:08 +02:00
2021-10-23 02:05:10 +02:00
```python
2021-10-22 17:31:08 +02:00
other_andrew = Customer.get('01FJM6PH661HCNNRC884H6K30C')
2021-10-23 02:05:10 +02:00
```
2021-10-25 23:21:39 +02:00
**Ready to learn more?** Check out the [getting started](docs/getting_started.md) guide.
2021-10-22 17:31:08 +02:00
2021-10-25 23:21:39 +02:00
Or, continue reading to see how Redis OM makes data validation a snap.
2021-10-22 17:31:08 +02:00
2021-10-25 23:21:39 +02:00
### Data Validation
2021-10-23 02:05:10 +02:00
2021-10-25 23:21:39 +02:00
Redis OM uses [Pydantic](pydantic-url) to validate data based on the type annotations you assign to fields in a model class.
2021-10-22 17:31:08 +02:00
2021-10-25 23:21:39 +02:00
This validation ensures that fields like `first_name`, which the `Customer` model marked as a `str`, are always string. **But every Redis OM model is also a Pydantic model**, so you can use Pydantic validators like `EmailStr`, `Pattern`, and many more for complex validation!
2021-10-22 17:31:08 +02:00
2021-10-25 23:21:39 +02:00
As an example, because we used the `EmailStr` validator, we'll get a validation error if we try to save a `Customer` with an invalid email address:
2021-10-22 17:31:08 +02:00
```python
Customer(
first_name="Andrew",
last_name="Brookins",
email="Not an email address!",
join_date=datetime.date.today(),
age=38,
bio="Python developer, works at Redis, Inc."
)
2021-10-25 23:21:39 +02:00
```
2021-10-22 17:31:08 +02:00
2021-10-25 23:21:39 +02:00
This code generates a validation error:
2021-10-22 17:31:08 +02:00
```
2021-10-25 23:21:39 +02:00
Traceback:
pydantic.error_wrappers.ValidationError: 1 validation error for Customer
email
value is not a valid email address (type=value_error.email)
```
What's great about this is **any existing Pydantic validator should work** as a drop-in type annotation with a Redis OM model. You can also write arbitrarily complex custom validations!
To learn more, see the [documentation on data validation](docs/validation.md).
2021-10-22 17:31:08 +02:00
2021-10-23 02:05:10 +02:00
2021-10-25 23:21:39 +02:00
#### Rich Queries and Embedded Models
2021-10-22 17:31:08 +02:00
2021-10-25 23:21:39 +02:00
Data modeling, validation, and saving models to Redis all work regardless of how you run Redis.
Next, we'll show you the **rich query expressions** and **embedded models** Redis OM provides when the [RediSearch](redisearch-url) and [RedisJSON](redis-json-url) modules are installed in your Redis deployment.
**TIP**: *Wait, what's a Redis module?* If you aren't familiar with Redis modules, review the "RediSearch and RedisJSON" section of this README.
2021-10-22 17:31:08 +02:00
### Querying
2021-10-25 23:21:39 +02:00
Let's make a small change to the `Customer` model we defined earlier to let Redis OM know that we want to query using the `last_name` and `age` fields:
```python
class Customer(HashModel):
first_name: str
last_name: str = Field(index=True)
email: EmailStr
join_date: datetime.date
age: int = Field(index=True)
bio: Optional[str]
```
Now, if we use this model with a Redis deployment that has the [RediSearch module](redisearch-url) installed, we can run queries like the following:
```python
# Find all customers with the last name "Brookins"
Customer.find(Customer.last_name == "Brookins").all()
2021-10-22 17:31:08 +02:00
2021-10-25 23:21:39 +02:00
# Find all customers that do NOT have the last name "Brookins"
Customer.find(Customer.last_name != "Brookins").all()
# Find all customers whose last name is "Brookins" OR whose age is
# 100 AND whose last name is "Smith"
Customer.find((Customer.last_name == "Brookins") | (
Customer.age == 100
) & (Customer.last_name == "Smith")).all()
```
2021-10-22 17:31:08 +02:00
2021-10-25 23:21:39 +02:00
These queries -- and more! -- are possible because **Redis OM manages indexes for you automatically**.
2021-10-20 01:51:55 +02:00
2021-10-25 23:21:39 +02:00
Querying with this index features a rich expression syntax inspired by the Django ORM, SQLAlchemy, and Peewee. We think you'll enjoy it!
To see more example queries, see the [documentation on querying](docs/querying.md).
### Embedded Models
Redis OM can store and query **nested models** like any document database, with the speed and power you get from Redis. Let's see how this works.
In the next example, we'll define a new `Address` model and embed it within the `Customer` model.
2021-10-20 00:06:50 +02:00
```python
import datetime
from typing import Optional
2021-10-22 15:36:15 +02:00
from redis_om.model import (
2021-10-20 00:06:50 +02:00
EmbeddedJsonModel,
JsonModel,
Field,
)
class Address(EmbeddedJsonModel):
address_line_1: str
address_line_2: Optional[str]
city: str = Field(index=True)
state: str = Field(index=True)
country: str
postal_code: str = Field(index=True)
class Customer(JsonModel):
first_name: str = Field(index=True)
last_name: str = Field(index=True)
email: str = Field(index=True)
join_date: datetime.date
age: int = Field(index=True)
bio: Optional[str] = Field(index=True, full_text_search=True,
default="")
# Creates an embedded model.
address: Address
```
2021-10-25 23:21:39 +02:00
With these two models and a Redis deployment with the RedisJSON module installed, we can run queries like the following:
2021-10-20 00:06:50 +02:00
```python
# Find all customers who live in San Antonio, TX
Customer.find(Customer.address.city == "San Antonio",
Customer.address.state == "TX")
```
2021-10-25 23:21:39 +02:00
To learn more, read the [documentation on embedded models](docs/embedded.md).
2021-10-20 00:06:50 +02:00
## 💻 Installation
Installation is simple with `pip`, Poetry, or Pipenv.
```sh
2021-10-20 01:53:19 +02:00
# With pip
2021-10-20 01:50:34 +02:00
$ pip install redis-om
2021-10-20 00:06:50 +02:00
# Or, using Poetry
2021-10-20 01:50:34 +02:00
$ poetry add redis-om
2021-10-20 00:06:50 +02:00
```
## 📚 Documentation
2021-10-25 23:21:39 +02:00
The Redis OM documentation is available [here](docs/index.md).
2021-10-20 00:06:50 +02:00
## ⛏️ Troubleshooting
If you run into trouble or have any questions, we're here to help!
First, check the [FAQ](docs/faq.md). If you don't find the answer there,
hit us up on the [Redis Discord Server](http://discord.gg/redis).
2021-10-20 01:53:48 +02:00
## ✨ RediSearch and RedisJSON
2021-10-25 23:21:39 +02:00
Some advanced features of Redis OM rely on core features from two source available Redis modules: [RediSearch](redisearch-url) and [RedisJSON](redis-json-url).
You can run these modules in your self-hosted Redis deployment, or you can use Redis Enterprise, which includes both modules.
2021-10-22 17:31:08 +02:00
To learn more, read [our documentation](docs/redis_modules.md).
2021-10-20 00:06:50 +02:00
## ❤️ Contributing
We'd love your contributions!
2021-10-22 15:36:15 +02:00
**Bug reports** are especially helpful at this stage of the project. [You can open a bug report on GitHub](https://github.com/redis-om/redis-om-python/issues/new).
2021-10-20 00:06:50 +02:00
2021-10-22 15:36:15 +02:00
You can also **contribute documentation** -- or just let us know if something needs more detail. [Open an issue on GitHub](https://github.com/redis-om/redis-om-python/issues/new) to get started.
2021-10-20 00:06:50 +02:00
## License
2021-10-22 17:31:08 +02:00
Redis OM uses the [BSD 3-Clause license][license-url].
2021-10-20 00:06:50 +02:00
<!-- Badges -->
2021-10-20 01:50:34 +02:00
[version-svg]: https://img.shields.io/pypi/v/redis-om?style=flat-square
[package-url]: https://pypi.org/project/redis-om/
2021-10-25 17:48:48 +02:00
[ci-svg]: https://img.shields.io/github/workflow/status/redis-developer/redis-om-python/ci?style=flat-square
[ci-url]: https://github.com/redis-developer/redis-om-python/actions/workflows/ci.yml
2021-10-25 19:03:37 +02:00
[license-image]: http://img.shields.io/badge/license-BSD_3--Clause-green.svg?style=flat-square
2021-10-20 00:06:50 +02:00
[license-url]: LICENSE
<!-- Links -->
2021-10-22 15:36:15 +02:00
[redis-om-website]: https://developer.redis.com
[redis-om-js]: https://github.com/redis-om/redis-om-js
[redis-om-dotnet]: https://github.com/redis-om/redis-om-dotnet
[redis-om-spring]: https://github.com/redis-om/redis-om-spring
2021-10-20 00:06:50 +02:00
[redisearch-url]: https://oss.redis.com/redisearch/
[redis-json-url]: https://oss.redis.com/redisjson/
[pydantic-url]: https://github.com/samuelcolvin/pydantic
[ulid-url]: https://github.com/ulid/spec