fix(qdrant): reject mixed range and non-range filter operators
Raise ValueError when a filter dict for a single field combines range operators (gt/gte/lt/lte) with non-range operators (eq/ne/in/nin/etc), preventing silent data loss where the non-range conditions were dropped. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -161,9 +161,15 @@ class Qdrant(VectorStoreBase):
|
||||
|
||||
ops = set(value.keys())
|
||||
range_ops = {"gt", "gte", "lt", "lte"}
|
||||
non_range_ops = ops - range_ops
|
||||
|
||||
if ops & range_ops:
|
||||
# Any combination of range operators: gt, gte, lt, lte
|
||||
if non_range_ops:
|
||||
raise ValueError(
|
||||
f"Cannot mix range operators ({ops & range_ops}) with "
|
||||
f"non-range operators ({non_range_ops}) for field '{key}'. "
|
||||
f"Use AND to combine them as separate conditions."
|
||||
)
|
||||
range_kwargs = {op: value[op] for op in range_ops if op in value}
|
||||
return FieldCondition(key=key, range=Range(**range_kwargs))
|
||||
elif "eq" in value:
|
||||
|
||||
@@ -541,5 +541,15 @@ class TestQdrantEnhancedFilters(unittest.TestCase):
|
||||
self.qdrant._build_field_condition("field", {"unknown_op": "foo"})
|
||||
self.assertIn("Unsupported", str(ctx.exception))
|
||||
|
||||
def test_mixed_range_and_non_range_raises_error(self):
|
||||
"""Mixing range ops with non-range ops should raise ValueError."""
|
||||
with self.assertRaises(ValueError):
|
||||
self.qdrant._build_field_condition("priority", {"gte": 5, "ne": 10})
|
||||
|
||||
def test_mixed_range_and_eq_raises_error(self):
|
||||
"""Mixing range ops with eq should raise ValueError."""
|
||||
with self.assertRaises(ValueError):
|
||||
self.qdrant._build_field_condition("score", {"gt": 0.5, "eq": 1.0})
|
||||
|
||||
def tearDown(self):
|
||||
del self.qdrant
|
||||
|
||||
Reference in New Issue
Block a user