Django filter JSONField list of dicts

早过忘川 提交于 2019-11-27 06:41:11

问题


I run Django 1.9 with the new JSONField and have the following Test model :

class Test(TimeStampedModel):
    actions = JSONField()

Let's say the action JSONField looks like this :

[
  {
    "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",
    }
  }
]

I want to be able to filter the foo1 and foo2 keys for every item of the list. When I do :

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

The Test is in the queryset. But when I do :

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

It isn't, which makes sense. I want to do something like :

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

Or

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

And have the Test in the queryset.

Any idea if this can be done and how ?


回答1:


If you wan't to filter your data by one of fields in your array of dicts, you can try this query:

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

It will list all Test objects that have at least one object in actions field that contains key fixed_key_1 of value foo2.

Also it should work for nested lookup, even if you don't know actual indexes:

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

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

In simple words, contains will ignore everything else.

Unfortunately, if nested element is an object, you must know key name. Lookup by value won't work in that case.




回答2:


You can use the django-jsonfield package, I guess it's already the one you are using.

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

So to search to make a search with a specific property, you can just do this:

def test_filter(**kwargs):
    result = Test.objects.filter(actions__contains=kwargs)
    return result

If you are using PostgreSQL, maybe you can take advantage of PostgreSQL specific model fields.

PS: If you are dealing with a lot of JSON structure you have maybe to consider using NoSQL Database.




回答3:


You should be able to use a __contains lookup for this and pass queried values as list as documented here. The lookup would behave exactly like ArrayField. So, something like this should work:

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


来源:https://stackoverflow.com/questions/34358278/django-filter-jsonfield-list-of-dicts

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!