redis / redis/redis-om-python

FindQuery doesn't support chaining .find() calls for dynamic query building

Open
#780 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Python
Stars
1.3k
Forks
128
PR merge metrics
No merged PRs in 30d

Description

Description

FindQuery objects don't support chaining .find() calls, which is a common pattern users expect from ORMs like Django. This leads to AttributeError and can be confusing.

Steps to Reproduce

from aredis_om import HashModel, Field, Migrator
import asyncio

class Product(HashModel, index=True):
    name: str = Field(index=True)
    category: str = Field(index=True)
    price: float = Field(index=True)

async def main():
    await Migrator().run()
    
    # This pattern feels natural but doesn't work:
    query = Product.find(Product.category == "electronics")
    query = query.find(Product.price > 100)  # ❌ AttributeError
    results = await query.all()

asyncio.run(main())

Error

AttributeError: 'FindQuery' object has no attribute 'find'

Expected Behavior

Users familiar with Django or SQLAlchemy expect to be able to chain filter calls:

# Django-style (what users expect):
query = Product.find(Product.category == "electronics")
query = query.find(Product.price > 100)
query = query.find(Product.in_stock > 0)
results = await query.all()

Current Workarounds

1. Use & operator to combine expressions
results = await Product.find(
    (Product.category == "electronics") & (Product.price > 100)
).all()
2. Pass multiple expressions to find()
results = await Product.find(
    Product.category == "electronics",
    Product.price > 100
).all()
3. Build a list of filters and unpack
filters = []
if category:
    filters.append(Product.category == category)
if min_price:
    filters.append(Product.price >= min_price)

if filters:
    results = await Product.find(*filters).all()
else:
    results = await Product.find().all()

Proposal

Either:

  1. Add .find() method to FindQuery - Allow chaining like Django's QuerySet
  2. Add .filter() method to FindQuery - Alternative name that adds conditions
  3. Document the correct patterns prominently - If chaining isn't supported, make the correct patterns very visible in docs

Impact

This is a common stumbling block when building dynamic queries (e.g., in API endpoints with optional filters). The workarounds work but aren't discoverable without reading source code or hitting the error.

Environment

  • redis-om version: 1.0.0 (current main branch)
  • Python version: 3.12

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the Product.find entry point and the FindQuery object referenced in the report; inspect how its existing multi-expression and & workarounds are represented. Confirm with maintainers whether chaining, filter(), or documentation is wanted, then add coverage or docs for dynamic filters and verify the chosen behavior with the reported query pattern.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, redis
Domain
backend, databases
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.