#31836 closed Bug (fixed)
JSONField's __contains and __contained_by lookups don't work with nested values on SQLite.
Reported by: | Mariusz Felisiak | Owned by: | Mariusz Felisiak |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 3.1 |
Severity: | Release blocker | Keywords: | |
Cc: | Sage Abdullah | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
SQLite doesn't provide a native way for testing containment of JSONField
. The current implementation works only for basic examples without supporting nested structures and doesn't follow "the general principle that the contained object must match the containing object as to structure and data contents, possibly after discarding some non-matching array elements or object key/value pairs from the containing object".
I'm not sure if it's feasible to emulate it in Python.
Some (not really complicated) examples that don't work:
diff --git a/tests/model_fields/test_jsonfield.py b/tests/model_fields/test_jsonfield.py index 9a9e1a1286..1acc5af73e 100644 --- a/tests/model_fields/test_jsonfield.py +++ b/tests/model_fields/test_jsonfield.py @@ -449,9 +449,14 @@ class TestQuerying(TestCase): tests = [ ({}, self.objs[2:5] + self.objs[6:8]), ({'baz': {'a': 'b', 'c': 'd'}}, [self.objs[7]]), + ({'baz': {'a': 'b'}}, [self.objs[7]]), + ({'baz': {'c': 'd'}}, [self.objs[7]]), ({'k': True, 'l': False}, [self.objs[6]]), ({'d': ['e', {'f': 'g'}]}, [self.objs[4]]), + ({'d': ['e']}, [self.objs[4]]), ([1, [2]], [self.objs[5]]), + ([1], [self.objs[5]]), + ([[2]], [self.objs[5]]), ({'n': [None]}, [self.objs[4]]), ({'j': None}, [self.objs[4]]), ]
Attachments (1)
Change History (10)
comment:1 by , 4 years ago
Triage Stage: | Unreviewed β Accepted |
---|
comment:2 by , 4 years ago
I've attached a draft solution but it's really hot and it doesn't handle list with dicts (...deep rabbit hole). IMO we should drop support for these lookups on SQLite, at least for now. Testing containment of JSONField
is really complicated, I hope SQLite and Oracle will prepare native solutions in future versions.
comment:3 by , 4 years ago
Owner: | changed from | to
---|---|
Status: | new β assigned |
comment:5 by , 4 years ago
Triage Stage: | Accepted β Ready for checkin |
---|
comment:8 by , 3 years ago
I hope SQLite and Oracle will prepare native solutions in future versions.
AFAIU there is a native solution for sqlite by using a join:
`
Foo.objects.filter(jsonsomepathcontains='bar')
SELECT β¦ FROM foo, json_each(foo.json, '$.some.path') WHERE json_each.value = 'bar';
`
comment:9 by , 3 years ago
Sorry for the messed up format. I will try again:
Foo.objects.filter(json__some__path__contains='bar') SELECT β¦ FROM foo, json_each(foo.json, '$.some.path') WHERE json_each.value = 'bar';
OK, grrrr... βΒ Just a case of doc-ing the limitations. π€¨
(Thanks)