使用JSONField的属性对Django查询集进行排序

时间:2018-10-07 23:35:34

标签: django django-models django-jsonfield

我有一个看起来像这样的模型:

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

data字段具有2个属性,nameage。现在,假设我想获得一个分页查询集(每个页面包含20个人),并使用一个过滤器,其中age大于25,并且该查询集将按降序排列。在通常的设置(即规范化数据库)中,我可以这样编写此查询:

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

现在,使用存储在JSONField中的键进行过滤和排序时,上述等效项是什么?我对此进行了研究,似乎它打算成为2.1的功能,但我似乎找不到任何相关的东西。

Link to the ticket about it being implemented in the future

我还有另一个问题。可以说我们使用JSONField进行过滤和排序。在这种情况下,ORM是否必须在发送前20个对象之前先获取所有对象,对其进行过滤和排序?也就是说,性能会合理降低吗?

很明显,我知道规范化的数据库在这些方面要好得多,但我的双手却束手无策。

1 个答案:

答案 0 :(得分:2)

您可以使用postgresql sql语法提取子字段。然后,它们可以与查询集过滤器中模型上的任何其他字段一样使用。

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

有关其他运算符和函数,请参见postgresql文档。 在某些情况下,您可能必须添加显式类型转换(例如,::int

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

性能会比使用适当的字段慢,但还不错。