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 ?
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.
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'}])
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With