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:
co-authored by
Claude Sonnet 4.6
parent
fb430b1a32
commit
b53507efd3
@@ -161,9 +161,15 @@ class Qdrant(VectorStoreBase):
|
|||||||
|
|
||||||
ops = set(value.keys())
|
ops = set(value.keys())
|
||||||
range_ops = {"gt", "gte", "lt", "lte"}
|
range_ops = {"gt", "gte", "lt", "lte"}
|
||||||
|
non_range_ops = ops - range_ops
|
||||||
|
|
||||||
if 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}
|
range_kwargs = {op: value[op] for op in range_ops if op in value}
|
||||||
return FieldCondition(key=key, range=Range(**range_kwargs))
|
return FieldCondition(key=key, range=Range(**range_kwargs))
|
||||||
elif "eq" in value:
|
elif "eq" in value:
|
||||||
|
|||||||
@@ -541,5 +541,15 @@ class TestQdrantEnhancedFilters(unittest.TestCase):
|
|||||||
self.qdrant._build_field_condition("field", {"unknown_op": "foo"})
|
self.qdrant._build_field_condition("field", {"unknown_op": "foo"})
|
||||||
self.assertIn("Unsupported", str(ctx.exception))
|
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):
|
def tearDown(self):
|
||||||
del self.qdrant
|
del self.qdrant
|
||||||
|
|||||||
Reference in New Issue
Block a user