Skip to content

Commit eb1faa6

Browse files
Correct query prefixing for embedded models to prevent field concatenation
1 parent c5068e5 commit eb1faa6

File tree

1 file changed

+22
-19
lines changed

1 file changed

+22
-19
lines changed

aredis_om/model/model.py

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ def score_field(self) -> str:
309309
class ExpressionProxy:
310310
def __init__(self, field: ModelField, parents: List[Tuple[str, "RedisModel"]]):
311311
self.field = field
312-
self.parents = parents
312+
self.parents = parents.copy() # Ensure a copy is stored
313313

314314
def __eq__(self, other: Any) -> Expression: # type: ignore[override]
315315
return Expression(
@@ -387,13 +387,14 @@ def __getattr__(self, item):
387387
attr = getattr(embedded_cls, item)
388388
else:
389389
attr = getattr(outer_type, item)
390+
390391
if isinstance(attr, self.__class__):
392+
# Clone the parents to ensure isolation
393+
new_parents = self.parents.copy()
391394
new_parent = (self.field.alias, outer_type)
392-
if new_parent not in attr.parents:
393-
attr.parents.append(new_parent)
394-
new_parents = list(set(self.parents) - set(attr.parents))
395-
if new_parents:
396-
attr.parents = new_parents + attr.parents
395+
if new_parent not in new_parents:
396+
new_parents.append(new_parent)
397+
attr.parents = new_parents
397398
return attr
398399

399400

@@ -624,18 +625,19 @@ def expand_tag_value(value):
624625

625626
@classmethod
626627
def resolve_value(
627-
cls,
628-
field_name: str,
629-
field_type: RediSearchFieldTypes,
630-
field_info: PydanticFieldInfo,
631-
op: Operators,
632-
value: Any,
633-
parents: List[Tuple[str, "RedisModel"]],
628+
cls,
629+
field_name: str,
630+
field_type: RediSearchFieldTypes,
631+
field_info: PydanticFieldInfo,
632+
op: Operators,
633+
value: Any,
634+
parents: List[Tuple[str, "RedisModel"]],
634635
) -> str:
636+
# The 'field_name' should already include the correct prefix
637+
result = ""
635638
if parents:
636639
prefix = "_".join([p[0] for p in parents])
637640
field_name = f"{prefix}_{field_name}"
638-
result = ""
639641
if field_type is RediSearchFieldTypes.TEXT:
640642
result = f"@{field_name}_fts:"
641643
if op is Operators.EQ:
@@ -792,15 +794,13 @@ def resolve_redisearch_query(cls, expression: ExpressionOrNegated) -> str:
792794

793795
if expression.op is Operators.ALL:
794796
if encompassing_expression_is_negated:
795-
# TODO: Is there a use case for this, perhaps for dynamic
796-
# scoring purposes with full-text search?
797797
raise QueryNotSupportedError(
798798
"You cannot negate a query for all results."
799799
)
800800
return "*"
801801

802802
if isinstance(expression.left, Expression) or isinstance(
803-
expression.left, NegatedExpression
803+
expression.left, NegatedExpression
804804
):
805805
result += f"({cls.resolve_redisearch_query(expression.left)})"
806806
elif isinstance(expression.left, ModelField):
@@ -827,6 +827,11 @@ def resolve_redisearch_query(cls, expression: ExpressionOrNegated) -> str:
827827
f"or an expression enclosed in parentheses. Docs: {ERRORS_URL}#E7"
828828
)
829829

830+
if isinstance(expression.left, ModelField) and expression.parents:
831+
# Build field_name using the specific parents for this expression
832+
prefix = "_".join([p[0] for p in expression.parents])
833+
field_name = f"{prefix}_{field_name}"
834+
830835
right = expression.right
831836

832837
if isinstance(right, Expression) or isinstance(right, NegatedExpression):
@@ -842,8 +847,6 @@ def resolve_redisearch_query(cls, expression: ExpressionOrNegated) -> str:
842847

843848
if isinstance(right, NegatedExpression):
844849
result += "-"
845-
# We're handling the RediSearch operator in this call ("-"), so resolve the
846-
# inner expression instead of the NegatedExpression.
847850
right = right.expression
848851

849852
result += f"({cls.resolve_redisearch_query(right)})"

0 commit comments

Comments
 (0)