fix(python): preserve zero distance bounds in hybrid search (#3652)

## Summary

- preserve explicit `0.0` distance bounds in synchronous hybrid search
- distinguish omitted `None` endpoints from zero-valued endpoints when
configuring the vector child query
- add a public end-to-end regression test for a zero upper bound

## Testing

- `cd python && uv run --extra tests pytest
python/tests/test_hybrid_query.py -q`
- `uv run --project python ruff format --check
python/python/lancedb/query.py python/python/tests/test_hybrid_query.py`
- `uv run --project python ruff check .`

Fixes #3651
This commit is contained in:
kid
2026-07-14 03:28:26 +08:00
committed by GitHub
parent a548e59d49
commit 7527890607
2 changed files with 15 additions and 1 deletions
+1 -1
View File
@@ -2634,7 +2634,7 @@ class LanceHybridQueryBuilder(LanceQueryBuilder):
self._vector_query.ef(self._ef)
if self._bypass_vector_index:
self._vector_query.bypass_vector_index()
if self._lower_bound or self._upper_bound:
if self._lower_bound is not None or self._upper_bound is not None:
self._vector_query.distance_range(
lower_bound=self._lower_bound, upper_bound=self._upper_bound
)
+14
View File
@@ -139,6 +139,20 @@ def test_hybrid_query_distance_range(sync_table: Table):
assert 0.2 <= dist.as_py() <= 0.5
def test_hybrid_query_applies_zero_upper_distance_bound(sync_table: Table):
result = (
sync_table.search(query_type="hybrid")
.vector([0.0, 0.4])
.text("elephant")
.distance_range(upper_bound=0.0)
.rerank(RRFReranker(return_score="all"))
.limit(4)
.to_arrow()
)
assert len(result) == 0
@pytest.mark.asyncio
async def test_hybrid_query_distance_range_async(table: AsyncTable):
reranker = RRFReranker(return_score="all")