Django 使用JSONField';s属性
我有一个类似这样的模型:Django 使用JSONField';s属性,django,django-models,django-jsonfield,Django,Django Models,Django Jsonfield,我有一个类似这样的模型: class Person(models.Model): data = JSONField() data字段有两个属性,name和age。现在,假设我想要得到一个分页的查询集(每个页面包含20个人),带有一个过滤器,其中age大于25,查询集按降序排列。在通常的设置(即规范化数据库)中,我可以这样编写此查询: person_list_page_1 = Person.objects.filter(age > 25).order_by('-age')[:20]
class Person(models.Model):
data = JSONField()
data
字段有两个属性,name
和age
。现在,假设我想要得到一个分页的查询集(每个页面包含20个人),带有一个过滤器,其中age
大于25,查询集按降序排列。在通常的设置(即规范化数据库)中,我可以这样编写此查询:
person_list_page_1 = Person.objects.filter(age > 25).order_by('-age')[:20]
现在,当使用存储在JSONField中的键进行过滤和排序时,上面的等价性是什么?我对此进行了研究,它似乎是2.1的一个特性,但我似乎找不到任何相关的东西
我还有一个问题。假设我们使用JSONField进行过滤和排序。在这种情况下,在发送前20个对象之前,ORM必须获取所有对象、过滤并对它们进行排序吗?也就是说,性能是否会合理地降低
显然,我知道规范化数据库更适合于这些事情,但我手头有点紧。您可以使用postgresql语法来提取子字段。然后,它们可以像queryset过滤器中模型上的任何其他字段一样使用
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
)
性能会比使用合适的字段慢,但也不错。您可以使用postgresql语法提取子字段。然后,它们可以像queryset过滤器中模型上的任何其他字段一样使用
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
)
性能将比使用正确的字段慢,但还不错。您是否尝试过
。order\u by('-data\u\u age')
?@AntoinePinsard是的,我遇到了以下错误:FieldError:无法将关键字“age”解析到字段中。不允许对“数据”进行连接。如果需要按字段进行索引、筛选或排序,为什么不将其设置为适当的列/模型字段,而不是滥用jsonfields。@HåkenLid很懒地假设这是滥用jsonfields,而不知道它是什么,并且它会这样做。正如我在问题中所说,它必须是一个jsonfield,是的,我完全意识到规范化的好处。您是否尝试过.order\u by('-data\u\u age')
?@AntoinePinsard是的,我得到这个错误:FieldError:无法将关键字“age”解析到字段中。不允许对“数据”进行连接。如果需要按字段进行索引、筛选或排序,为什么不将其设置为适当的列/模型字段,而不是滥用jsonfields。@HåkenLid很懒地假设这是滥用jsonfields,而不知道它是什么,并且它会这样做。正如我在问题中所说的,它必须是一个jsonfield,是的,我完全了解规范化的好处。关于类型转换,如果它是一个格式为“-10.50”的字符串,即存储为字符串的十进制数,该怎么办。我找不到Postgres的数字类型转换。应该可以。例如,试试::数字(99,2)
。Django将Postgresql数值类型转换为pythonDecimal
type。非常感谢,这基本上解决了我所有的问题。刚刚在10000多行上进行了测试,速度惊人!关于类型转换,如果它是一个格式为“-10.50”的字符串,即存储为字符串的十进制数,该怎么办。我找不到Postgres的数字类型转换。应该可以。例如,试试::数字(99,2)
。Django将Postgresql数值类型转换为pythonDecimal
type。非常感谢,这基本上解决了我所有的问题。刚刚在10000多行上进行了测试,速度惊人!