关于python:如何在Django JSONField中过滤JSON数组

How to filter JSON Array in Django JSONField

我对在Django 2.0.3中过滤(postgres)JSONField感到疯狂。
json存储为数组。例如

1
tasks = [{"task":"test","level":"10"},{"task":"test 123","level":"20"}]

我尝试过的事情:

1
2
3
4
5
myModel.objects.filter("tasks__task__contains"="test")
myModel.objects.filter("tasks_task__0__contains"="test")
myModel.objects.filter("tasks__0__task__contains"="test")
myModel.objects.filter("tasks_task__0_x__contains"="test")
myModel.objects.filter("tasks__0_x__task__contains"="test")

出了什么问题?
我想做的是一个icontains-但正如我已经读过的那样,现在在Django中的jsonfields上不支持icontains ...


正确的答案应该是:

1
myModel.objects.filter(tasks__contains=[{"task":"test"}])

您可能需要添加更多过滤器以缩小并加快查询的速度,例如

1
myModel.objects.filter(Q(tasks_level=10, tasks__contains=[{"task":"test"}]))


filter中的contains关键字非常强大。您可以使用以下命令从Jsonb列类型的词典数组中的任何字段中过滤出MyModel中的行。

1
MyModel.objects.filter(tasks__contains=["task":"test"])

这是我发现的最适合ORM的解决方案,无需区分大小写的方法。
如前所述,对于不敏感的情况,Django没有json的icontains,请使用

MyModel.objects.extra("")
为此,请在postgres中插入" ILIKE"运算符的SQL查询。


1
MyModel.objects.filter(tasks__contains=["task":"test"])

我在这里看到两个问题。

1)Django过滤器选项用于过滤Django对象,而不是字段中的对象。您绝对可以过滤包含任务" test"的对象,但不能过滤该对象中JSONField中的特定任务(您需要首先检索django对象的内容,然后在其他步骤中进行查询)

2)据我了解JSONField上的django文档,contains运算符仅检查字典中的键或列表中的元素。将其附加到查找查询中,以希望它比较一个值,就像我理解您的示例一样,因此将不起作用。但是,可以用contains查询字典。在您的情况下,这应该适用于查询django对象:

1
myModel.objects.filter("tasks__contains"={"task":"test"})

如果您只对一个词典感兴趣,而对其他词典不感兴趣,则需要通过随后提取正确的对象来扩展此查询:

1
2
3
4
matching_objects = myModel.objects.filter("tasks__contains"={"task":"test"})
for matching_object in matching_objects:
    for matching_task in [task for task in matching_object.tasks if"task" in task and task["task"] =="test" ]:
        print"found task", matching_task

另请参阅此相关的stackoverflow答案,以查找使用contains的JSONFields。