Skip to content

Commit

Permalink
feat: JSONB Contained by
Browse files Browse the repository at this point in the history
  • Loading branch information
Chart.js committed Oct 3, 2022
1 parent 6bf7f9a commit d45a156
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 0 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ class JSONBTestModel(ormar.Model):
data: dict = ormar_pg_ext.JSONB()
```

##### jsonb_contained_by

The maps to the [`contains`](https://docs.sqlalchemy.org/en/14/dialects/postgresql.html#sqlalchemy.dialects.postgresql.JSONB.Comparator.contained_by) operator in Postgres.

```python
await JSONBTestModel.objects.filter(data__jsonb_contained_by=dict(key="value")).all()
```

##### jsonb_contains

The maps to the [`contains`](https://docs.sqlalchemy.org/en/14/dialects/postgresql.html#sqlalchemy.dialects.postgresql.JSONB.Comparator.contains) operator in Postgres.
Expand Down
13 changes: 13 additions & 0 deletions src/ormar_postgres_extensions/fields/jsonb.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@
from sqlalchemy.dialects import postgresql


def jsonb_contained_by(self, other: Any) -> ormar.queryset.clause.FilterGroup:
"""
works as postgresql `column <@ VALUE::jsonb`
:param other: value to check against operator
:type other: Any
:return: FilterGroup for operator
:rtype: ormar.queryset.clause.FilterGroup
"""
return self._select_operator(op="jsonb_contained_by", other=other)


def jsonb_contains(self, other: Any) -> ormar.queryset.clause.FilterGroup:
"""
works as postgresql `column @> VALUE::jsonb`
Expand All @@ -17,6 +28,7 @@ def jsonb_contains(self, other: Any) -> ormar.queryset.clause.FilterGroup:

# Need to patch the filter objects to support JSONB specifc actions
FIELD_ACCESSOR_MAP = [
("jsonb_contained_by", jsonb_contained_by),
("jsonb_contains", jsonb_contains),
]

Expand All @@ -28,6 +40,7 @@ def jsonb_contains(self, other: Any) -> ormar.queryset.clause.FilterGroup:
# These lines allow Ormar to lookup the new filter methods and map
# it to the correct PGSQL functions
ACCESSOR_MAP = [
("jsonb_contained_by", "contained_by"),
("jsonb_contains", "contains"),
]

Expand Down
21 changes: 21 additions & 0 deletions tests/fields/test_jsonb.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,24 @@ async def test_contains_array_text(db):

found = await JSONBTestModel.objects.filter(data__jsonb_contains="4").all()
assert len(found) == 0


@pytest.mark.asyncio
async def test_contained_by(db):
await JSONBTestModel(data=json.dumps(dict(key1="foo"))).save()
await JSONBTestModel(data=json.dumps(dict(key2="bar"))).save()

found = await JSONBTestModel.objects.filter(
data__jsonb_contained_by=dict(key1="foo")
).all()
assert len(found) == 1

found = await JSONBTestModel.objects.filter(
data__jsonb_contained_by=dict(key1="foo", key2="bar")
).all()
assert len(found) == 2

found = await JSONBTestModel.objects.filter(
data__jsonb_contains=dict(key1="bar")
).all()
assert len(found) == 0

0 comments on commit d45a156

Please sign in to comment.