Skip to content

Commit 74b55f5

Browse files
committed
Implement __len filter for ArrayField
1 parent 2c32925 commit 74b55f5

File tree

4 files changed

+37
-0
lines changed

4 files changed

+37
-0
lines changed

tests/fields/test_array.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,17 @@ async def test_overlap_ints(self):
135135
"array", flat=True
136136
)
137137
self.assertEqual(sorted(list(found)), [[1, 2, 3], [2, 3, 4], [3, 4, 5]])
138+
139+
async def test_array_length(self):
140+
await testmodels.ArrayFields.create(array=[1, 2, 3])
141+
await testmodels.ArrayFields.create(array=[1])
142+
await testmodels.ArrayFields.create(array=[1, 2])
143+
144+
found = await testmodels.ArrayFields.filter(array__len=3).values_list("array", flat=True)
145+
self.assertEqual(list(found), [[1, 2, 3]])
146+
147+
found = await testmodels.ArrayFields.filter(array__len=1).values_list("array", flat=True)
148+
self.assertEqual(list(found), [[1]])
149+
150+
found = await testmodels.ArrayFields.filter(array__len=0).values_list("array", flat=True)
151+
self.assertEqual(list(found), [])

tortoise/backends/base_postgres/executor.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
postgres_array_contains,
1212
postgres_array_contained_by,
1313
postgres_array_overlap,
14+
postgres_array_length,
1415
)
1516
from tortoise.contrib.postgres.json_functions import (
1617
postgres_json_contained_by,
@@ -32,6 +33,7 @@
3233
json_filter,
3334
posix_regex,
3435
search,
36+
array_length,
3537
)
3638

3739

@@ -52,6 +54,7 @@ class BasePostgresExecutor(BaseExecutor):
5254
json_filter: postgres_json_filter,
5355
posix_regex: postgres_posix_regex,
5456
insensitive_posix_regex: postgres_insensitive_posix_regex,
57+
array_length: postgres_array_length,
5558
}
5659

5760
def _prepare_insert_statement(

tortoise/contrib/postgres/array_functions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import Any, Sequence, Union
33

44
from pypika_tortoise.terms import Array, BasicCriterion, Criterion, Term
5+
from pypika_tortoise.functions import Function
56

67

78
class PostgresArrayOperators(str, Enum):
@@ -23,3 +24,8 @@ def postgres_array_contained_by(field: Term, value: Sequence[Any]) -> Criterion:
2324

2425
def postgres_array_overlap(field: Term, value: Sequence[Any]) -> Criterion:
2526
return BasicCriterion(PostgresArrayOperators.OVERLAP, field, Array(*value))
27+
28+
29+
def postgres_array_length(field: Term, value: int) -> Criterion:
30+
"""Returns a criterion that checks if array length equals the given value"""
31+
return Function("array_length", field, 1).eq(value)

tortoise/filters.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ def string_encoder(value: Any, instance: "Model", field: Field) -> str:
7373
return str(value)
7474

7575

76+
def int_encoder(value: Any, instance: "Model", field: Field) -> int:
77+
return int(value)
78+
79+
7680
def json_encoder(value: Any, instance: "Model", field: Field) -> dict:
7781
return value
7882

@@ -238,6 +242,10 @@ def array_overlap(field: Term, value: Union[Any, Sequence[Any]]) -> Criterion:
238242
raise NotImplementedError("must be overridden in each executor")
239243

240244

245+
def array_length(field: Term, value: int) -> Criterion:
246+
raise NotImplementedError("must be overridden in each executor")
247+
248+
241249
##############################################################################
242250
# Filter resolvers
243251
##############################################################################
@@ -430,6 +438,12 @@ def get_array_filter(field_name: str, source_field: str) -> dict[str, FilterInfo
430438
"source_field": source_field,
431439
"operator": array_overlap,
432440
},
441+
f"{field_name}__len": {
442+
"field": field_name,
443+
"source_field": source_field,
444+
"operator": array_length,
445+
"value_encoder": int_encoder,
446+
},
433447
}
434448

435449

0 commit comments

Comments
 (0)