Ordering Django querysets using a JSONField's properties

自作多情 提交于 2019-12-13 20:19:29

问题


I have a model that kinda looks like this:

class Person(models.Model):
    data = JSONField()

The data field has 2 properties, name, and age. Now, lets say I want to get a paginated queryset (each page containing 20 people), with a filter where age is greater than 25, and the queryset is to be ordered in descending order. In a usual setup, that is, a normalized database, I can write this query like so:

person_list_page_1 = Person.objects.filter(age > 25).order_by('-age')[:20]

Now, what is the equivalence of the above when filtering and ordering using keys stored in the JSONField? I have researched into this, and it seems it was meant to be a feature for 2.1, but I can't seem to find anything relevant.

Link to the ticket about it being implemented in the future

I also have another question. Lets say we filter and order using the JSONField. Will the ORM have to get all the objects, filter, and order them before sending the first 20 in such a case? That is, will performance be legitimately slower?

Obviously, I know a normalized database is far better for these things, but my hands are kinda tied.


回答1:


You can use the postgresql sql syntax to extract subfields. Then they can be used just as any other field on the model in queryset filters.

from django.db.models.expressions import RawSQL
Person.objects.annotate(
    age=RawSQL("(data->>'age')::int", [])
).filter(age__gte=25).order_by('-age')[:20]

See the postgresql docs for other operators and functions. In some cases, you might have to add explicit typecasts (::int, for example)

https://www.postgresql.org/docs/current/static/functions-json.html

Performance will be slower than with a proper field, but it's not bad.



来源:https://stackoverflow.com/questions/52693812/ordering-django-querysets-using-a-jsonfields-properties

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!