Django筛选JSONField字典列表

21

我使用具有新JSONField的Django 1.9,并具有以下Test模型:

class Test(TimeStampedModel):
    actions = JSONField()

假设动作JSONField看起来像这样:

[
  {
    "fixed_key_1": "foo1",
    "fixed_key_2": {
      "random_key_1": "bar1",
      "random_key_2": "bar2",
    }
  },
  {
    "fixed_key_1": "foo2",
    "fixed_key_2": {
      "random_key_3": "bar2",
      "random_key_4": "bar3",
    }
  }
]

我希望能够筛选列表中每个条目的foo1和foo2键。

当我执行以下操作:

>>> Test.objects.filter(actions__1__fixed_key_1="foo2")

测试在查询集中。但是当我执行以下操作时:

>>> Test.objects.filter(actions__0__fixed_key_1="foo2")

这并不合理。我想做类似于:

>>> Test.objects.filter(actions__values__fixed_key_1="foo2")

或者

>>> Test.objects.filter(actions__values__fixed_key_2__values__contains="bar3")

你是否有任何想法可以在查询集中进行测试,如何实现?

3个回答

34

如果您想通过字典数组中的一个字段来过滤数据,可以尝试使用以下查询:

Test.objects.filter(actions__contains=[{'fixed_key_1': 'foo2'}])

它将列出所有至少有一个包含键名为fixed_key_1且值为foo2的对象在actions字段中的Test对象。

此外,它应该能够处理嵌套查找,即使您不知道实际的索引:

Test(actions=[
    {'fixed_key_1': 'foo4', 'fixed_key_3': [
        {'key1': 'foo2'},
    ]}
}).save()

Test.objects.filter(actions__contains=[{'fixed_key_3': [{'key1': 'foo2'}]}])

简单来说,contains将忽略其他所有内容。

不幸的是,如果嵌套元素是一个对象,你必须知道键名。在这种情况下,按值查找将无法工作。


在尝试第一个时,我遇到了这个错误:TypeError: Lookup type 'contains' not supported with list argument,通过操作查询来减少错误,如下所示:Test.objects.filter(actions__contains={'fixed_key_1': 'foo2'}) - Manish Shah

11

您应该可以使用__contains查找,按文档此处传递查询值的列表。该查找行为类似于ArrayField。所以,像这样做应该可以:

Test.objects.filter(actions__contains=[{'fixed_key_1': 'foo2'}])

3

您可以使用django-jsonfield包,我猜这已经是您正在使用的包了。

from jsonfield import JSONField
class Test(TimeStampedModel):
    actions = JSONField()

所以,要使用特定属性进行搜索,只需执行以下操作:
def test_filter(**kwargs):
    result = Test.objects.filter(actions__contains=kwargs)
    return result

如果你正在使用PostgreSQL,也许可以利用PostgreSQL 特定模型字段
PS:如果你处理大量JSON结构,也许需要考虑使用NoSQL数据库。

1
我已经在使用PostgreSQL的JSONField特定模型字段(from django.contrib.postgres.fields import JSONField)。您的解决方案适用于已知your_property(在我的情况下是fixed_key_1fixed_key_2),但是当我不知道your_property(在我的情况下是random_key_#)时,我该怎么办? - Scentle5S
你应该将 {'fixed_key_1': 'foo2'} 设置为你的参数,我已经更新了代码以使用通用函数。 - Dhia
1
问题是我不知道 your_property 是什么。它可能是任何东西,而且我并不关心它,只想知道 JSONField 是否包含给定字符串在其任何值中,无论深度如何。 - Scentle5S
1
请问您能否举个例子,向您的test_filter方法中插入什么内容,以便查看JSONField中是否包含“bar3”,而您又不知道除了fixed_key_1fixed_key_2之外的任何键?因为我认为我们谈论的问题不一样。 - Scentle5S
1
这不起作用。它说这不是 JSON 类型的有效语法。 - Scentle5S
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接