Skip to content

Commit 57fe8a2

Browse files
authored
adding xfix style queries (#610)
1 parent 5ef3d27 commit 57fe8a2

File tree

3 files changed

+95
-1
lines changed

3 files changed

+95
-1
lines changed

aredis_om/model/model.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
TypeVar,
2323
Union,
2424
)
25-
from typing import get_args as typing_get_args, no_type_check
25+
from typing import get_args as typing_get_args
26+
from typing import no_type_check
2627

2728
from more_itertools import ichunked
2829
from redis.commands.json.path import Path
@@ -112,6 +113,9 @@ class Operators(Enum):
112113
NOT_IN = 11
113114
LIKE = 12
114115
ALL = 13
116+
STARTSWITH = 14
117+
ENDSWITH = 15
118+
CONTAINS = 16
115119

116120
def __str__(self):
117121
return str(self.name)
@@ -346,6 +350,21 @@ def __rshift__(self, other: Any) -> Expression:
346350
left=self.field, op=Operators.NOT_IN, right=other, parents=self.parents
347351
)
348352

353+
def startswith(self, other: Any) -> Expression:
354+
return Expression(
355+
left=self.field, op=Operators.STARTSWITH, right=other, parents=self.parents
356+
)
357+
358+
def endswith(self, other: Any) -> Expression:
359+
return Expression(
360+
left=self.field, op=Operators.ENDSWITH, right=other, parents=self.parents
361+
)
362+
363+
def contains(self, other: Any) -> Expression:
364+
return Expression(
365+
left=self.field, op=Operators.CONTAINS, right=other, parents=self.parents
366+
)
367+
349368
def __getattr__(self, item):
350369
if item.startswith("__"):
351370
raise AttributeError("cannot invoke __getattr__ with reserved field")
@@ -691,6 +710,21 @@ def resolve_value(
691710
result += "-(@{field_name}:{{{expanded_value}}})".format(
692711
field_name=field_name, expanded_value=expanded_value
693712
)
713+
elif op is Operators.STARTSWITH:
714+
expanded_value = cls.expand_tag_value(value)
715+
result += "(@{field_name}:{{{expanded_value}*}})".format(
716+
field_name=field_name, expanded_value=expanded_value
717+
)
718+
elif op is Operators.ENDSWITH:
719+
expanded_value = cls.expand_tag_value(value)
720+
result += "(@{field_name}:{{*{expanded_value}}})".format(
721+
field_name=field_name, expanded_value=expanded_value
722+
)
723+
elif op is Operators.CONTAINS:
724+
expanded_value = cls.expand_tag_value(value)
725+
result += "(@{field_name}:{{*{expanded_value}*}})".format(
726+
field_name=field_name, expanded_value=expanded_value
727+
)
694728

695729
return result
696730

tests/test_hash_model.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,3 +852,26 @@ class TypeWithUuid(HashModel):
852852
item = TypeWithUuid(uuid=uuid.uuid4())
853853

854854
await item.save()
855+
856+
857+
@py_test_mark_asyncio
858+
async def test_xfix_queries(members, m):
859+
member1, member2, member3 = members
860+
861+
result = await m.Member.find(m.Member.first_name.startswith("And")).first()
862+
assert result.first_name == "Andrew"
863+
864+
result = await m.Member.find(m.Member.last_name.endswith("ins")).first()
865+
assert result.first_name == "Andrew"
866+
867+
result = await m.Member.find(m.Member.last_name.contains("ook")).first()
868+
assert result.first_name == "Andrew"
869+
870+
result = await m.Member.find(m.Member.bio % "great*").first()
871+
assert result.first_name == "Andrew"
872+
873+
result = await m.Member.find(m.Member.bio % "*rty").first()
874+
assert result.first_name == "Andrew"
875+
876+
result = await m.Member.find(m.Member.bio % "*eat*").first()
877+
assert result.first_name == "Andrew"

tests/test_json_model.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -934,3 +934,40 @@ class TypeWithUuid(JsonModel):
934934
item = TypeWithUuid(uuid=uuid.uuid4())
935935

936936
await item.save()
937+
938+
939+
@py_test_mark_asyncio
940+
async def test_xfix_queries(m):
941+
await m.Member(
942+
first_name="Steve",
943+
last_name="Lorello",
944+
945+
join_date=today,
946+
bio="Steve is a two-bit hacker who loves Redis.",
947+
address=m.Address(
948+
address_line_1="42 foo bar lane",
949+
city="Satellite Beach",
950+
state="FL",
951+
country="USA",
952+
postal_code="32999",
953+
),
954+
age=34,
955+
).save()
956+
957+
result = await m.Member.find(m.Member.first_name.startswith("Ste")).first()
958+
assert result.first_name == "Steve"
959+
960+
result = await m.Member.find(m.Member.last_name.endswith("llo")).first()
961+
assert result.first_name == "Steve"
962+
963+
result = await m.Member.find(m.Member.address.city.contains("llite")).first()
964+
assert result.first_name == "Steve"
965+
966+
result = await m.Member.find(m.Member.bio % "tw*").first()
967+
assert result.first_name == "Steve"
968+
969+
result = await m.Member.find(m.Member.bio % "*cker").first()
970+
assert result.first_name == "Steve"
971+
972+
result = await m.Member.find(m.Member.bio % "*ack*").first()
973+
assert result.first_name == "Steve"

0 commit comments

Comments
 (0)