redis-search-django
Index Django models into Redis Query Engine (RediSearch) and query them with the same lookups you already use in the ORM.
Django stays the source of truth. You declare a Document, signals (or redisearch populate) keep a search copy in Redis, and you query with Document.objects.filter(...).
Documentation: https://saadmk11.github.io/redis-search-django/ · Getting started · Demo app · Contribute
Features
- Declarative documents — one
Documentclass per model, auto-discovered fromdocuments.py - Live sync — create / update / delete (including related FK, O2O, and M2M) update Redis automatically
- Nested data —
fields.Objectandfields.Nestedfor related rows (JSON or HASH storage) - Django-style query —
filter,exclude,search,Q,order_by, stockPaginator - ORM hand-off —
to_queryset()returns Django rows in RediSearch rank order - Facets and aggregates —
.facets()and a first-classAggregatebuilder overFT.AGGREGATE - Vector search — embed on save with a pluggable function, then
knn()next tofilter() - Async —
acount,aget,ato_queryset, async index writes, and async views - Index lifecycle —
redisearchfor create, update, populate, rebuild, blue-green reindex, and verify - Debug overlay — optional per-view Redis query / write inspector (
SearchDebugMixin) - Queues without a dependency — swap
SIGNAL_PROCESSORto run the same writes in Celery, django-q, or RQ
Requirements
| Runtime | Versions |
|---|---|
| Python | 3.10 – 3.15 (free-threaded from 3.15t) |
| Django | 5.2, 6.0, 6.1 |
| redis-py | ≥ 8.0 (installed with the package) |
| Redis | 8+ with Query Engine and RedisJSON |
Quick start
uv add redis-search-django
# or
pip install redis-search-django
# settings.py
INSTALLED_APPS = [
...,
"redis_search_django",
]
# Optional. Default is redis://localhost:6379/0
REDIS_SEARCH = {
"URL": "redis://localhost:6379/0",
}
This repo’s Compose file starts Redis Stack (6379) and Redis Insight (8001):
docker compose up -d
Declare a document in documents.py so the app can discover it:
# shop/documents.py
from redis_search_django.documents import Document
from .models import Product
class ProductDocument(Document):
class Django:
model = Product
fields = ["name", "description", "price", "available"]
Create the index and load existing rows:
python manage.py redisearch create
python manage.py redisearch populate
Search:
from redis_search_django import Q
from shop.documents import ProductDocument
hits = ProductDocument.objects.filter(
Q(name__search="shoes") | Q(description__search="shoes"),
price__lte=150,
available=True,
)[:20]
for hit in hits:
hit.pk, hit.score, hit.name
Use redis_search_django.Q, not django.db.models.Q. Full walkthrough: Getting started.
Query API
DocumentQuerySet is lazy and clone-on-write, like Django.
| Need | Call |
|---|---|
| Keyword + filters | objects.filter(name__search="shoes", price__lte=150) |
| Exact / membership | name__exact, tags__name__in=["sale"], available=True |
| Ranges | price__gte, created_at__range=(start, end) |
| Missing values | category__isnull=True (optional Object uses INDEXMISSING) |
| Exclude | objects.exclude(tags__name="discontinued") |
| Sort / slice | .order_by("-price")[:20] |
| Facets | .facets("category__name", "tags__name") |
| Aggregations | .aggregate(Aggregate().group_by("vendor__name").avg("price", "avg")) |
| Nearest neighbors | .knn("comfortable running shoes", k=10) |
| Django rows | .to_queryset() |
| Async | acount(), aget(), ato_queryset(), async for hit in qs |
Lookups, pagination, and views: Query. Vector fields and knn(): Vector search.
Indexing
| Command | Purpose |
|---|---|
redisearch create |
Create missing indexes |
redisearch update |
Apply compatible schema changes |
redisearch populate |
Write current Django rows into Redis |
redisearch rebuild |
Drop, create, and populate |
redisearch reindex |
In-place rebuild (--blue-green for a zero-downtime swap) |
redisearch verify |
Diff Django PKs vs Redis (--repair to fix drift) |
redisearch drop / info / check |
Remove an index, print FT.INFO, check drift |
Details: Indexing. Upgrading from 0.1: Migrate.
Example app
example/ is a catalog you can click through — search, KNN, aggregations, async, and CRUD. How to run it and what each page is: Demo app.
Development
uv sync --group dev
docker compose up -d
uv run pytest
| Check | Command |
|---|---|
| Tests + 100% coverage | uv run pytest |
| Full Python / Django matrix | uvx --with tox-uv tox |
How to run linters, the matrix, and open a PR: Contribute.