diff --git a/README.md b/README.md index 1c8d329..025c242 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,15 @@ await JSONBTestModel.objects.filter(data__jsonb_has_all=array(["key1", "key2"])) ``` ##### jsonb_has_any + +The maps to the [`has_any`](https://docs.sqlalchemy.org/en/14/dialects/postgresql.html#sqlalchemy.dialects.postgresql.JSONB.Comparator.has_any) operator in Postgres. + +```python +from sqlalchemy.dialects.postgres import array + +await JSONBTestModel.objects.filter(data__jsonb_has_any=array(["key1", "key2"])).all() +``` + ##### jsonb_has_key The maps to the [`has_key`](https://docs.sqlalchemy.org/en/14/dialects/postgresql.html#sqlalchemy.dialects.postgresql.JSONB.Comparator.has_key) operator in Postgres. diff --git a/src/ormar_postgres_extensions/fields/jsonb.py b/src/ormar_postgres_extensions/fields/jsonb.py index 481c421..b9fc667 100644 --- a/src/ormar_postgres_extensions/fields/jsonb.py +++ b/src/ormar_postgres_extensions/fields/jsonb.py @@ -37,6 +37,17 @@ def jsonb_has_all(self, other: Any) -> ormar.queryset.clause.FilterGroup: return self._select_operator(op="jsonb_has_all", other=other) +def jsonb_has_any(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_has_any", other=other) + + def jsonb_has_key(self, other: Any) -> ormar.queryset.clause.FilterGroup: """ works as postgresql `column ? VALUE::jsonb` @@ -53,6 +64,7 @@ def jsonb_has_key(self, other: Any) -> ormar.queryset.clause.FilterGroup: ("jsonb_contained_by", jsonb_contained_by), ("jsonb_contains", jsonb_contains), ("jsonb_has_all", jsonb_has_all), + ("jsonb_has_any", jsonb_has_any), ("jsonb_has_key", jsonb_has_key), ] @@ -67,6 +79,7 @@ def jsonb_has_key(self, other: Any) -> ormar.queryset.clause.FilterGroup: ("jsonb_contained_by", "contained_by"), ("jsonb_contains", "contains"), ("jsonb_has_all", "has_all"), + ("jsonb_has_any", "has_any"), ("jsonb_has_key", "has_key"), ] diff --git a/tests/fields/test_jsonb.py b/tests/fields/test_jsonb.py index bba5f5d..d2c7640 100644 --- a/tests/fields/test_jsonb.py +++ b/tests/fields/test_jsonb.py @@ -145,6 +145,27 @@ async def test_has_all(db): assert len(found) == 1 +@pytest.mark.asyncio +async def test_has_any(db): + await JSONBTestModel(data=json.dumps(dict(key1="foo", key3=2))).save() + await JSONBTestModel(data=json.dumps(dict(key2="bar"))).save() + + found = await JSONBTestModel.objects.filter( + data__jsonb_has_any=array(["key1"]) + ).all() + assert len(found) == 1 + + found = await JSONBTestModel.objects.filter( + data__jsonb_has_any=array(["key1", "key3"]) + ).all() + assert len(found) == 1 + + found = await JSONBTestModel.objects.filter( + data__jsonb_has_any=array(["key1", "key2"]) + ).all() + assert len(found) == 2 + + @pytest.mark.asyncio async def test_has_key_object(db): await JSONBTestModel(data=json.dumps(dict(key1="foo"))).save()