fix: merge same-key operator dicts in AND metadata filters (#4853)

This commit is contained in:
Yarizakura
2026-04-20 21:54:02 +05:30
committed by GitHub
parent 4b09943092
commit 8ba225cec8
2 changed files with 61 additions and 13 deletions
+29 -13
View File
@@ -1239,15 +1239,15 @@ class Memory(MemoryBase):
def _process_metadata_filters(self, metadata_filters: Dict[str, Any]) -> Dict[str, Any]:
"""
Process enhanced metadata filters and convert them to vector store compatible format.
Args:
metadata_filters: Enhanced metadata filters with operators
Returns:
Dict of processed filters compatible with vector store
"""
processed_filters = {}
def process_condition(key: str, condition: Any) -> Dict[str, Any]:
if not isinstance(condition, dict):
# Simple equality: {"key": "value"}
@@ -1255,7 +1255,7 @@ class Memory(MemoryBase):
# Wildcard: match everything for this field (implementation depends on vector store)
return {key: "*"}
return {key: condition}
result = {}
for operator, value in condition.items():
# Map platform operators to universal format that can be translated by each vector store
@@ -1271,6 +1271,14 @@ class Memory(MemoryBase):
raise ValueError(f"Unsupported metadata filter operator: {operator}")
return result
def merge_filters(target: Dict[str, Any], source: Dict[str, Any]) -> None:
"""Merge source into target, deep-merging nested operator dicts for the same key."""
for key, value in source.items():
if key in target and isinstance(target[key], dict) and isinstance(value, dict):
target[key].update(value)
else:
target[key] = value
for key, value in metadata_filters.items():
if key == "AND":
# Logical AND: combine multiple conditions
@@ -1278,7 +1286,7 @@ class Memory(MemoryBase):
raise ValueError("AND operator requires a list of conditions")
for condition in value:
for sub_key, sub_value in condition.items():
processed_filters.update(process_condition(sub_key, sub_value))
merge_filters(processed_filters, process_condition(sub_key, sub_value))
elif key == "OR":
# Logical OR: Pass through to vector store for implementation-specific handling
if not isinstance(value, list) or not value:
@@ -1288,7 +1296,7 @@ class Memory(MemoryBase):
for condition in value:
or_condition = {}
for sub_key, sub_value in condition.items():
or_condition.update(process_condition(sub_key, sub_value))
merge_filters(or_condition, process_condition(sub_key, sub_value))
processed_filters["$or"].append(or_condition)
elif key == "NOT":
# Logical NOT: Pass through to vector store for implementation-specific handling
@@ -1298,11 +1306,11 @@ class Memory(MemoryBase):
for condition in value:
not_condition = {}
for sub_key, sub_value in condition.items():
not_condition.update(process_condition(sub_key, sub_value))
merge_filters(not_condition, process_condition(sub_key, sub_value))
processed_filters["$not"].append(not_condition)
else:
processed_filters.update(process_condition(key, value))
merge_filters(processed_filters, process_condition(key, value))
return processed_filters
def _has_advanced_operators(self, filters: Dict[str, Any]) -> bool:
@@ -2682,6 +2690,14 @@ class AsyncMemory(MemoryBase):
raise ValueError(f"Unsupported metadata filter operator: {operator}")
return result
def merge_filters(target: Dict[str, Any], source: Dict[str, Any]) -> None:
"""Merge source into target, deep-merging nested operator dicts for the same key."""
for key, value in source.items():
if key in target and isinstance(target[key], dict) and isinstance(value, dict):
target[key].update(value)
else:
target[key] = value
for key, value in metadata_filters.items():
if key == "AND":
# Logical AND: combine multiple conditions
@@ -2689,7 +2705,7 @@ class AsyncMemory(MemoryBase):
raise ValueError("AND operator requires a list of conditions")
for condition in value:
for sub_key, sub_value in condition.items():
processed_filters.update(process_condition(sub_key, sub_value))
merge_filters(processed_filters, process_condition(sub_key, sub_value))
elif key == "OR":
# Logical OR: Pass through to vector store for implementation-specific handling
if not isinstance(value, list) or not value:
@@ -2699,7 +2715,7 @@ class AsyncMemory(MemoryBase):
for condition in value:
or_condition = {}
for sub_key, sub_value in condition.items():
or_condition.update(process_condition(sub_key, sub_value))
merge_filters(or_condition, process_condition(sub_key, sub_value))
processed_filters["$or"].append(or_condition)
elif key == "NOT":
# Logical NOT: Pass through to vector store for implementation-specific handling
@@ -2709,10 +2725,10 @@ class AsyncMemory(MemoryBase):
for condition in value:
not_condition = {}
for sub_key, sub_value in condition.items():
not_condition.update(process_condition(sub_key, sub_value))
merge_filters(not_condition, process_condition(sub_key, sub_value))
processed_filters["$not"].append(not_condition)
else:
processed_filters.update(process_condition(key, value))
merge_filters(processed_filters, process_condition(key, value))
return processed_filters