我正在使用django和postgres,并且在我的模型中有一堆JSON字段(其中一些非常大且详细)。我正在从基于char的字段切换到jsonb字段,这允许我在字段内的键上filter
,并且我想知道是否有任何方法可以获得等效字段通过调用查询集values
方法获益。
我想做的是Car
模型options
JSONField,就像
qset = Car.objects.filter(options__interior__color='red')
vals = qset.values('options__interior__material')
请原谅蹩脚的玩具问题,但希望它可以解决这个问题。这里filter
调用完全符合我的要求,但对values
的调用似乎并不了解JSON字段的特殊性。我收到错误,因为values
无法找到名为" interior"加入。是否还有一些其他语法或选项可以让我的工作成功?
似乎是对现有功能的一个非常明显的扩展,但到目前为止我没有找到任何类似于文档或堆栈溢出或谷歌搜索的引用。
在玩完之后,通过在上面的两行代码之间插入以下代码,可能会有点捏造:
qset=qset.annotate(options__interior__material=RawSQL("SELECT options->'interior'->'material'",()))
我说" fudged"因为它似乎是滥用符号而需要对整数索引进行特殊处理。
仍然希望有更好的答案。
答案 0 :(得分:1)
我可以使用以下方式建议更清洁:
django的Func
https://docs.djangoproject.com/en/2.0/ref/models/expressions/#func-expressions
和postgres函数jsonb_extract_path_text
https://www.postgresql.org/docs/9.5/static/functions-json.html
from django.db.models import F, Func, CharField, Value Car.objects.all().annotate(options__interior__material = Func( F('options'), Value('interior'), Value('material'), function='jsonb_extract_path_text' ), )
答案 1 :(得分:1)
也许更好的解决方案(对于Django> = 1.11)是使用这样的东西:
from django.contrib.postgres.fields.jsonb import KeyTextTransform
Car.objects.filter(options__interior__color='red').annotate(
interior_material=KeyTextTransform('material', KeyTextTransform('interior', 'options'))
).values('interior_material')
请注意,您可以嵌套KeyTextTransform
表达式来提取所需的值。
答案 2 :(得分:0)
Car.objects.extra(select={'interior_material': "options#>'{interior, material}'"})
.filter(options__interior__color='red')
.values('interior_material')
您可以利用.extra()
并添加postgres jsonb运算符
Postgres jsonb运算符:https://www.postgresql.org/docs/9.5/static/functions-json.html#FUNCTIONS-JSON-OP-TABLE