fix(vector_stores/turbopuffer): apply all filter operators instead of dropping them (#6564)

This commit is contained in:
Yash Singh
2026-09-25 15:53:35 +05:30
committed by GitHub
parent 545306db5a
commit ccd216cff0
2 changed files with 54 additions and 4 deletions
+20 -4
View File
@@ -131,6 +131,18 @@ class TurbopufferDB(VectorStoreBase):
))
return results
# Maps mem0 filter operators to their Turbopuffer equivalents.
OPERATOR_MAP = {
"eq": "Eq",
"ne": "NotEq",
"gt": "Gt",
"gte": "Gte",
"lt": "Lt",
"lte": "Lte",
"in": "In",
"nin": "NotIn",
}
def _convert_filters(self, filters: Optional[Dict]):
"""
Convert mem0 filters to Turbopuffer filter format.
@@ -143,10 +155,14 @@ class TurbopufferDB(VectorStoreBase):
conditions = []
for key, value in filters.items():
if isinstance(value, dict):
if "gte" in value:
conditions.append((key, "Gte", value["gte"]))
if "lte" in value:
conditions.append((key, "Lte", value["lte"]))
for op, operand in value.items():
tpuf_op = self.OPERATOR_MAP.get(op)
if tpuf_op is None:
raise ValueError(
f"Unsupported filter operator '{op}' for field '{key}'. "
f"Supported operators: {sorted(self.OPERATOR_MAP)}"
)
conditions.append((key, tpuf_op, operand))
else:
conditions.append((key, "Eq", value))
+34
View File
@@ -276,6 +276,40 @@ class TestConvertFilters:
assert ("user_id", "Eq", "u1") in conditions
assert ("score", "Gte", 0.5) in conditions
def test_gt_operator_not_dropped(self, db):
"""Regression: {"gt": ...} was silently dropped, returning unfiltered results."""
result = db._convert_filters({"age": {"gt": 18}})
assert result == ("age", "Gt", 18)
@pytest.mark.parametrize(
"op,expected_token",
[
("eq", "Eq"),
("ne", "NotEq"),
("gt", "Gt"),
("gte", "Gte"),
("lt", "Lt"),
("lte", "Lte"),
("in", "In"),
("nin", "NotIn"),
],
)
def test_all_operators_mapped(self, db, op, expected_token):
operand = [1, 2] if op in ("in", "nin") else 5
result = db._convert_filters({"age": {op: operand}})
assert result == ("age", expected_token, operand)
def test_multiple_operators_on_one_field(self, db):
result = db._convert_filters({"age": {"gt": 18, "lt": 65}})
assert result[0] == "And"
conditions = result[1]
assert ("age", "Gt", 18) in conditions
assert ("age", "Lt", 65) in conditions
def test_unknown_operator_raises(self, db):
with pytest.raises(ValueError, match="Unsupported filter operator"):
db._convert_filters({"age": {"between": [1, 2]}})
# ── search ───────────────────────────────────────────────────────────