21

我使用新的 JSONField 运行 Django 1.9 并具有以下测试模型:

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")

并在查询集中进行测试。

知道这是否可以做到以及如何做到吗?

4

3 回答 3

30

如果您不想通过 dicts 数组中的某个字段过滤数据,可以尝试以下查询:

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

它将列出Test在字段中至少有一个对象actions包含fixed_key_1value 键的所有对象foo2

即使您不知道实际索引,它也应该适用于嵌套查找:

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

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

简而言之,包含将忽略其他所有内容。

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

于 2016-02-12T15:59:48.670 回答
11

您应该能够__contains对此使用查找并将查询值作为列表传递,如此所述。查找的行为与 ArrayField 完全相同。所以,这样的事情应该有效:

Test.objects.filter(actions__contains=[{'fixed_key_1': 'foo2'}])
于 2015-12-18T15:52:43.917 回答
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 数据库。

于 2015-12-18T15:27:49.227 回答