redis / redis-om-python

Object mapping, and more, for Redis and Python
MIT License
1.12k stars 112 forks source link

How to query lenght of list? #321

Open dehuy69 opened 2 years ago

dehuy69 commented 2 years ago

Hello, how can i query condition which use len of list in redis_om?

class Person(JsonModel):
    first_name: str = Field(index=True)
    last_name: str = Field(index=True)
    age: PositiveInt = Field(index=True)
    address: Address
    skills: List[str] = Field(index=True)
    personal_statement: str = Field(index=True, full_text_search=True)

oneData = {
  "first_name": "A string, the person's first or given name",
  "last_name": "A string, the person's last or surname",
  "age": 36,
  "address": {
    "street_number": 56,
    "unit": "A string, optional unit number e.g. A or 1",
    "street_name": "A string, name of the street they live on",
    "city": "A string, name of the city they live in",
    "state": "A string, state, province or county that they live in",
    "postal_code": "A string, their zip or postal code",
    "country": "A string, country that they live in."
  },
  "personal_statement": "A string, free text personal statement",
  "skills": [
    "A string: a skill the person has",
    "A string: another still that the person has"
  ]
}

person = Person(**oneData)
person.save()

Migrator().run()
Person.find((Person.skills.__len__() > 1).all() 

I want query condition of length of skills list Can not find out anything in document and I tried many ways. Pls help!

wiseaidev commented 2 years ago

I think the translated SQL query would be something like:

SELECT  *, COUNT(skills)
FROM Person
GROUP BY skills
HAVING COUNT(skills) > 1;

Or redis search version:

FT.AGGREGATE "idx:skills" GROUPBY 4 @skills  REDUCE COUNT 4 AS nb_skills FILTER "nb_skills > 1"

Not sure if redis-om has a HAVING functionality I can confirm now it is not supported yet in redis-om, and it is being tracked in issues/258, i may work on it. However, if you want to accomplish it with the current setup, you can do something like:

results = Person.find().all()
results = [person for person in results if len(person.skills) > 1])
simonprickett commented 2 years ago

Closing - refer to #258 thanks.