deprecate python VectorQuery (#267)

* deprecate python VectorQuery

* remove import
This commit is contained in:
egolearner 2026-05-12 14:55:49 +08:00 committed by GitHub
parent 269c611f78
commit ce468af29b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 210 additions and 134 deletions

View File

@ -15,7 +15,7 @@ from zvec import (
CollectionSchema,
Collection,
Doc,
VectorQuery,
Query,
)
from support_helper import *

View File

@ -833,7 +833,7 @@ class TestIndexDDL:
)
query_result: list[Doc] = coll.query(
VectorQuery(field_name=vector_name, vector=query_vector),
Query(field_name=vector_name, vector=query_vector),
include_vector=False,
topk=len(docs),
)

View File

@ -11,7 +11,7 @@ from zvec import (
CollectionSchema,
Collection,
Doc,
VectorQuery,
Query,
StatusCode,
)
from distance_helper import *
@ -456,7 +456,7 @@ def singledoc_and_check(
for k, v in DEFAULT_VECTOR_FIELD_NAME.items():
if v != {}:
query_result = collection.query(
VectorQuery(field_name=v, vector=insert_doc.vectors[v]),
Query(field_name=v, vector=insert_doc.vectors[v]),
topk=10,
)
assert len(query_result) > 0, (
@ -512,7 +512,7 @@ def updatedoc_partial_check(
for k, v in DEFAULT_VECTOR_FIELD_NAME.items():
if v != {}:
query_result = collection.query(
VectorQuery(field_name=v, vector=update_doc_full.vectors[v]),
Query(field_name=v, vector=update_doc_full.vectors[v]),
topk=10,
)
assert len(query_result) > 0, (
@ -580,7 +580,7 @@ def batchdoc_and_check(collection, multiple_docs, doc_num, operator="insert"):
first_doc = multiple_docs[doc_num - 1]
for k, v in DEFAULT_VECTOR_FIELD_NAME.items():
query_result = collection.query(
VectorQuery(field_name=v, vector=first_doc.vectors[v]),
Query(field_name=v, vector=first_doc.vectors[v]),
topk=1024,
)
assert len(query_result) > 0, (

View File

@ -19,7 +19,7 @@ from fixture_helper import *
from params_helper import *
from zvec import StatusCode
from zvec.extension import QwenReRanker, RrfReRanker, WeightedReRanker
from zvec.model import Collection, Doc, VectorQuery
from zvec.model import Collection, Doc
from zvec.model.param import (
CollectionOption,
FlatIndexParam,
@ -81,7 +81,7 @@ def batchdoc_and_check(
first_doc = multiple_docs[doc_num - 1]
for k, v in DEFAULT_VECTOR_FIELD_NAME.items():
query_result = collection.query(
VectorQuery(field_name=v, vector=first_doc.vectors[v]),
Query(field_name=v, vector=first_doc.vectors[v]),
topk=1024,
include_vector=True,
)
@ -152,7 +152,7 @@ def batchdoc_and_check_ivf(
for k, v in DEFAULT_VECTOR_FIELD_NAME.items():
if v in ["vector_fp16_field", "vector_fp32_field"]:
query_result = collection.query(
VectorQuery(field_name=v, vector=first_doc.vectors[v]),
Query(field_name=v, vector=first_doc.vectors[v]),
topk=1024,
include_vector=True,
)
@ -571,7 +571,7 @@ class TestCollectionQuery:
full_collection_new, multiple_docs, doc_num, operator="insert"
)
for k, v in DEFAULT_VECTOR_FIELD_NAME.items():
query_result = full_collection_new.query(VectorQuery(field_name=v, id="1"))
query_result = full_collection_new.query(Query(field_name=v, id="1"))
assert len(query_result) > 0
query_doc = full_collection_new.fetch(ids=["1"])
query_vector = query_doc["1"].vector(v)
@ -595,9 +595,7 @@ class TestCollectionQuery:
)
for k, v in DEFAULT_VECTOR_FIELD_NAME.items():
if v in ["vector_fp16_field", "vector_fp32_field"]:
query_result = full_collection_ivf.query(
VectorQuery(field_name=v, id="1")
)
query_result = full_collection_ivf.query(Query(field_name=v, id="1"))
assert len(query_result) > 0
query_doc = full_collection_ivf.fetch(ids=["1"])
query_vector = query_doc["1"].vector(v)
@ -635,22 +633,22 @@ class TestCollectionQuery:
query_vector = doc_vectors[v]
if topk and filter:
query_result = full_collection_new.query(
Query(field_name=v, vector=query_vector),
filter=filter,
vectors=VectorQuery(field_name=v, vector=query_vector),
topk=topk,
)
elif topk and not filter:
query_result = full_collection_new.query(
VectorQuery(field_name=v, vector=query_vector), topk=topk
Query(field_name=v, vector=query_vector), topk=topk
)
elif not topk and filter:
query_result = full_collection_new.query(
Query(field_name=v, vector=query_vector),
filter=filter,
vectors=VectorQuery(field_name=v, vector=query_vector),
)
else:
query_result = full_collection_new.query(
VectorQuery(field_name=v, vector=query_vector)
Query(field_name=v, vector=query_vector)
)
assert len(query_result) > 0, (
f"Expected at least 1 query result, but got {len(query_result)}"
@ -680,7 +678,7 @@ class TestCollectionQuery:
)
query_vector = doc_vectors[v]
query_result = full_collection_ivf.query(
VectorQuery(field_name=v, vector=query_vector),
Query(field_name=v, vector=query_vector),
topk=1024,
)
assert len(query_result) > 0, (
@ -707,16 +705,16 @@ class TestCollectionQuery:
single_query_results = {}
for k, v in DEFAULT_VECTOR_FIELD_NAME.items():
single_query_results[v] = full_collection.query(
VectorQuery(field_name=v, vector=doc_vectors[v])
Query(field_name=v, vector=doc_vectors[v])
)
expected_rrf_scores = calculate_multi_vector_rrf_scores(single_query_results)
multi_query_vectors = []
for k, v in DEFAULT_VECTOR_FIELD_NAME.items():
multi_query_vectors.append(VectorQuery(field_name=v, vector=doc_vectors[v]))
multi_query_vectors.append(Query(field_name=v, vector=doc_vectors[v]))
rrf_reranker = RrfReRanker(topn=3)
multi_query_result = full_collection.query(
vectors=multi_query_vectors,
multi_query_vectors,
reranker=rrf_reranker,
)
assert len(multi_query_result) > 0, (
@ -773,7 +771,7 @@ class TestCollectionQuery:
single_query_results = {}
for k, v in DEFAULT_VECTOR_FIELD_NAME.items():
single_query_results[v] = full_collection.query(
VectorQuery(field_name=v, vector=doc_vectors[v])
Query(field_name=v, vector=doc_vectors[v])
)
expected_weighted_scores = calculate_multi_vector_weighted_scores(
single_query_results, weights, MetricType.IP
@ -781,10 +779,10 @@ class TestCollectionQuery:
multi_query_vectors = []
for k, v in DEFAULT_VECTOR_FIELD_NAME.items():
multi_query_vectors.append(VectorQuery(field_name=v, vector=doc_vectors[v]))
multi_query_vectors.append(Query(field_name=v, vector=doc_vectors[v]))
multi_query_result = full_collection.query(
vectors=multi_query_vectors,
multi_query_vectors,
reranker=weighted_reranker,
)
assert len(multi_query_result) > 0, (
@ -868,10 +866,8 @@ class TestCollectionQuery:
)
query_vector = doc_vectors[v]
query_result = full_collection_new.query(
Query(field_name=v, vector=query_vector, param=HnswQueryParam(ef=ef)),
filter=filter,
vectors=VectorQuery(
field_name=v, vector=query_vector, param=HnswQueryParam(ef=ef)
),
topk=topk,
)
assert len(query_result) > 0, (
@ -903,10 +899,10 @@ class TestCollectionQuery:
query_vector = doc_vectors[v]
with pytest.raises(Exception) as exc_info:
full_collection.query(
filter=filter,
vectors=VectorQuery(
Query(
field_name=v, vector=query_vector, param=HnswQueryParam(ef=ef)
),
filter=filter,
topk=topk,
)
assert INCOMPATIBLE_CONSTRUCTOR_ERROR_MSG in str(exc_info.value)
@ -935,12 +931,12 @@ class TestCollectionQuery:
query_vector = doc_vectors[v]
query_result = full_collection_ivf.query(
filter=filter,
vectors=VectorQuery(
Query(
field_name=v,
vector=query_vector,
param=IVFQueryParam(nprobe=nprobe),
),
filter=filter,
topk=topk,
)
assert len(query_result) > 0
@ -977,12 +973,12 @@ class TestCollectionQuery:
query_vector = doc_vectors[v]
with pytest.raises(Exception) as exc_info:
full_collection_ivf.query(
# filter=filter,
vectors=VectorQuery(
Query(
field_name=v,
vector=query_vector,
param=IVFQueryParam(nprobe=nprobe),
),
# filter=filter,
topk=topk,
)
assert INCOMPATIBLE_CONSTRUCTOR_ERROR_MSG in str(exc_info.value)
@ -1005,10 +1001,10 @@ class TestCollectionQuery:
query_vector = doc_vectors[v]
if v in ["vector_fp16_field", "vector_fp32_field"]:
full_collection.query(
filter=filter,
vectors=VectorQuery(
Query(
field_name=v, vector=query_vector, param=HnswIndexParam()
),
filter=filter,
)
assert INCOMPATIBLE_FUNCTION_ERROR_MSG in str(exc_info.value)
@ -1018,56 +1014,56 @@ class TestCollectionQuery:
[
(
"Non-existent vector field name",
lambda ref_dense_vector: VectorQuery(
lambda ref_dense_vector: Query(
field_name="nonexistent_vector", vector=ref_dense_vector
),
"Expected exception for non-existent vector field name",
),
(
"Invalid vector data type for dense vector (string instead of list)",
lambda ref_dense_vector: VectorQuery(
lambda ref_dense_vector: Query(
field_name="vector_fp32_field", vector="invalid_vector_data"
),
"Expected exception for invalid dense vector data type",
),
(
"Invalid vector data type for sparse vector (list instead of dict)",
lambda ref_dense_vector: VectorQuery(
lambda ref_dense_vector: Query(
field_name="sparse_fp32", vector=[1.0, 2.0, 3.0]
),
"Expected exception for invalid sparse vector data type",
),
(
"Empty vector data for dense vector",
lambda ref_dense_vector: VectorQuery(
lambda ref_dense_vector: Query(
field_name="vector_fp32_field", vector=[]
),
"Expected exception for empty dense vector data",
),
(
"Invalid dimension for dense vector",
lambda ref_dense_vector: VectorQuery(
lambda ref_dense_vector: Query(
field_name="vector_fp32_field", vector=[1.0, 2.0]
), # Only 2 dimensions instead of 128
"Expected exception for invalid dense vector dimension",
),
(
"Non-existent document ID for by_id query",
lambda ref_dense_vector: VectorQuery(
lambda ref_dense_vector: Query(
field_name="vector_fp32_field", id="999"
), # Non-existent ID
"Expected exception for non-existent document ID",
),
(
"Both vector and id specified (invalid combination)",
lambda ref_dense_vector: VectorQuery(
lambda ref_dense_vector: Query(
field_name="vector_fp32_field", vector=ref_dense_vector, id="5"
),
"Expected exception for specifying both vector and id",
),
(
"Neither vector nor id specified",
lambda ref_dense_vector: VectorQuery(
lambda ref_dense_vector: Query(
field_name="vector_fp32_field"
), # Neither vector nor id
"Expected exception for specifying neither vector nor id",
@ -1092,7 +1088,7 @@ class TestCollectionQuery:
ref_dense_vector = ref_doc.vector("vector_fp32_field")
with pytest.raises(Exception) as exc_info:
full_collection.query(vectors=[vector_query(ref_dense_vector)])
full_collection.query([vector_query(ref_dense_vector)])
assert exc_info.value is not None, expected_error_msg
@pytest.mark.parametrize("filter", ["int32_field >= 3 and int32_field <= 7"])
@ -1112,8 +1108,8 @@ class TestCollectionQuery:
)
query_vector = doc_vectors[v]
full_collection.query(
Query(field_name=v, vector=query_vector),
filter=filter,
vectors=VectorQuery(field_name=v, vector=query_vector),
param=HnswIndexParam(),
topk=3,
)
@ -1262,9 +1258,7 @@ class TestCollectionConcurrencyOperations:
else:
query_vector = [0.1] * 128
result = full_collection.query(
VectorQuery(
field_name="vector_fp32_field", vector=query_vector
),
Query(field_name="vector_fp32_field", vector=query_vector),
topk=3,
)

View File

@ -26,8 +26,8 @@ from zvec import (
Collection,
Doc,
FieldSchema,
Query,
VectorSchema,
VectorQuery,
)
@ -182,11 +182,11 @@ class TestCollectionExceptionHandling:
"Expected exception for missing ids parameter"
)
def test_query_missing_vectorquery_field_name(self, test_collection: Collection):
def test_query_missing_query_field_name(self, test_collection: Collection):
with pytest.raises(Exception) as exc_info:
result = test_collection.query(vectors=[VectorQuery()])
result = test_collection.query([Query()])
assert exc_info.value is not None, (
"Expected exception for missing VectorQuery field_name parameter"
"Expected exception for missing Query field_name parameter"
)
def test_add_column_missing_field_schema(self, test_collection: Collection):

View File

@ -478,7 +478,7 @@ class TestCollectionOpen:
# Test vector query functionality for dense vectors
query_vector_dense = [0.1] * 128
vector_query_result = opened_coll.query(
VectorQuery(field_name="dense", vector=query_vector_dense)
Query(field_name="dense", vector=query_vector_dense)
)
assert len(vector_query_result) > 0, (
f"Expected at least 1 vector query result, but got {len(vector_query_result)}"
@ -529,7 +529,7 @@ class TestCollectionOpen:
# Test vector query functionality for sparse vectors
query_vector_sparse = {1: 1.0, 2: 2.0, 3: 3.0}
sparse_vector_query_result = opened_coll.query(
VectorQuery(field_name="sparse", vector=query_vector_sparse)
Query(field_name="sparse", vector=query_vector_sparse)
)
assert len(sparse_vector_query_result) > 0, (
f"Expected at least 1 sparse vector query result, but got {len(sparse_vector_query_result)}"

View File

@ -15,7 +15,7 @@
import pytest
from zvec.typing import DataType, StatusCode, MetricType, QuantizeType
from zvec.model import Collection, Doc, VectorQuery
from zvec.model import Collection, Doc, Query
from zvec.model.param import (
CollectionOption,
InvertIndexParam,
@ -158,7 +158,7 @@ def get_ground_truth_for_vector_query(
else:
full_result = collection.query(
VectorQuery(field_name=field_name, vector=query_vector),
Query(field_name=field_name, vector=query_vector),
topk=min(len(all_docs), 1024),
include_vector=True,
)
@ -214,7 +214,7 @@ def calculate_recall_at_k(
print("Starting %dth query" % i)
query_result_list = collection.query(
VectorQuery(field_name=field_name, vector=query_vector),
Query(field_name=field_name, vector=query_vector),
topk=1024,
include_vector=True,
)

View File

@ -29,7 +29,7 @@ from zvec import (
LogType,
OptimizeOption,
StatusCode,
VectorQuery,
Query,
VectorSchema,
)
@ -934,7 +934,7 @@ class TestCollectionQuery:
):
with pytest.raises(ValueError):
collection_with_single_doc.query(
VectorQuery(
Query(
field_name="dense",
id=single_doc.id,
vector=single_doc.vector("dense"),
@ -950,19 +950,19 @@ class TestCollectionQuery:
def test_collection_with_error_query_vector(
self, collection_with_multiple_docs: Collection, multiple_docs
):
query = VectorQuery(
query = Query(
field_name="dense", vector=multiple_docs[0].vector("dense"), param=[1, 2, 3]
)
with pytest.raises(TypeError):
result = collection_with_multiple_docs.query(
filter="id in (1)", topk=100, vectors=query
query, filter="id in (1)", topk=100
)
def test_collection_query_by_id(
self, collection_with_multiple_docs: Collection, multiple_docs
):
result = collection_with_multiple_docs.query(
VectorQuery(field_name="dense", id=multiple_docs[0].id)
Query(field_name="dense", id=multiple_docs[0].id)
)
assert len(result) == 10
@ -972,12 +972,8 @@ class TestCollectionQuery:
with pytest.raises(ValueError):
collection_with_multiple_docs.query(
[
VectorQuery(
field_name="dense", vector=multiple_docs[0].vector("dense")
),
VectorQuery(
field_name="dense", vector=multiple_docs[0].vector("dense")
),
Query(field_name="dense", vector=multiple_docs[0].vector("dense")),
Query(field_name="dense", vector=multiple_docs[0].vector("dense")),
]
)

View File

@ -34,7 +34,7 @@ from zvec import (
HnswRabitqQueryParam,
MetricType,
VectorSchema,
VectorQuery,
Query,
)
@ -285,13 +285,13 @@ class TestHnswRabitqCollectionQuery:
):
"""Test querying by vector with HNSW RaBitQ index."""
query_vector = multiple_docs[0].vector("embedding")
query = VectorQuery(
query = Query(
field_name="embedding",
vector=query_vector,
param=HnswRabitqQueryParam(ef=300),
)
result = collection_with_multiple_docs.query(vectors=query, topk=10)
result = collection_with_multiple_docs.query(queries=query, topk=10)
assert len(result) > 0
assert len(result) <= 10
@ -304,13 +304,13 @@ class TestHnswRabitqCollectionQuery:
self, collection_with_multiple_docs: Collection, multiple_docs: list[Doc]
):
"""Test querying by document ID with HNSW RaBitQ index."""
query = VectorQuery(
query = Query(
field_name="embedding",
id=multiple_docs[0].id,
param=HnswRabitqQueryParam(ef=300),
)
result = collection_with_multiple_docs.query(vectors=query, topk=10)
result = collection_with_multiple_docs.query(queries=query, topk=10)
assert len(result) > 0
assert len(result) <= 10
@ -321,21 +321,21 @@ class TestHnswRabitqCollectionQuery:
query_vector = multiple_docs[0].vector("embedding")
# Test with ef=100
query_100 = VectorQuery(
query_100 = Query(
field_name="embedding",
vector=query_vector,
param=HnswRabitqQueryParam(ef=100),
)
result_100 = collection_with_multiple_docs.query(vectors=query_100, topk=10)
result_100 = collection_with_multiple_docs.query(queries=query_100, topk=10)
assert len(result_100) > 0
# Test with ef=500
query_500 = VectorQuery(
query_500 = Query(
field_name="embedding",
vector=query_vector,
param=HnswRabitqQueryParam(ef=500),
)
result_500 = collection_with_multiple_docs.query(vectors=query_500, topk=10)
result_500 = collection_with_multiple_docs.query(queries=query_500, topk=10)
assert len(result_500) > 0
def test_query_with_topk(
@ -343,18 +343,18 @@ class TestHnswRabitqCollectionQuery:
):
"""Test querying with different topk values."""
query_vector = multiple_docs[0].vector("embedding")
query = VectorQuery(
query = Query(
field_name="embedding",
vector=query_vector,
param=HnswRabitqQueryParam(ef=300),
)
# Test topk=5
result_5 = collection_with_multiple_docs.query(vectors=query, topk=5)
result_5 = collection_with_multiple_docs.query(queries=query, topk=5)
assert len(result_5) <= 5
# Test topk=20
result_20 = collection_with_multiple_docs.query(vectors=query, topk=20)
result_20 = collection_with_multiple_docs.query(queries=query, topk=20)
assert len(result_20) <= 20
def test_query_with_filter(
@ -362,7 +362,7 @@ class TestHnswRabitqCollectionQuery:
):
"""Test querying with filter conditions."""
query_vector = multiple_docs[0].vector("embedding")
query = VectorQuery(
query = Query(
field_name="embedding",
vector=query_vector,
param=HnswRabitqQueryParam(ef=300),
@ -370,7 +370,7 @@ class TestHnswRabitqCollectionQuery:
# Query with id filter
result = collection_with_multiple_docs.query(
vectors=query, topk=10, filter="id < 50"
queries=query, topk=10, filter="id < 50"
)
assert len(result) > 0
for doc in result:
@ -381,14 +381,14 @@ class TestHnswRabitqCollectionQuery:
):
"""Test querying with specific output fields."""
query_vector = multiple_docs[0].vector("embedding")
query = VectorQuery(
query = Query(
field_name="embedding",
vector=query_vector,
param=HnswRabitqQueryParam(ef=300),
)
result = collection_with_multiple_docs.query(
vectors=query, topk=10, output_fields=["id", "name"]
queries=query, topk=10, output_fields=["id", "name"]
)
assert len(result) > 0
@ -401,14 +401,14 @@ class TestHnswRabitqCollectionQuery:
):
"""Test querying with vector data included in results."""
query_vector = multiple_docs[0].vector("embedding")
query = VectorQuery(
query = Query(
field_name="embedding",
vector=query_vector,
param=HnswRabitqQueryParam(ef=300),
)
result = collection_with_multiple_docs.query(
vectors=query, topk=10, include_vector=True
queries=query, topk=10, include_vector=True
)
assert len(result) > 0
@ -536,12 +536,12 @@ class TestHnswRabitqCollectionOptimizeAndReopen:
# Verify data is still accessible after optimize
query_vector = multiple_docs[0].vector("embedding")
query = VectorQuery(
query = Query(
field_name="embedding",
vector=query_vector,
param=HnswRabitqQueryParam(ef=300),
)
result_before_close = coll.query(vectors=query, topk=10)
result_before_close = coll.query(query, topk=10)
assert len(result_before_close) > 0
# Close collection (destroy will close it)
@ -554,12 +554,12 @@ class TestHnswRabitqCollectionOptimizeAndReopen:
assert reopened_coll.stats.doc_count == len(multiple_docs)
# Execute query on reopened collection
query_after_reopen = VectorQuery(
query_after_reopen = Query(
field_name="embedding",
vector=query_vector,
param=HnswRabitqQueryParam(ef=300),
)
result_after_reopen = reopened_coll.query(vectors=query_after_reopen, topk=10)
result_after_reopen = reopened_coll.query(query_after_reopen, topk=10)
assert len(result_after_reopen) > 0
assert len(result_after_reopen) <= 10

View File

@ -31,6 +31,7 @@ from zvec import (
OptimizeOption,
HnswQueryParam,
IVFQueryParam,
Query,
VectorQuery,
IndexType,
MetricType,
@ -373,9 +374,9 @@ class TestHnswQueryParam:
# assert param.scale_factor == 40
class TestVectorQuery:
class TestQuery:
def test_init_with_valid_id(self):
vq = VectorQuery(field_name="embedding", id="doc123")
vq = Query(field_name="embedding", id="doc123")
assert vq.field_name == "embedding"
assert vq.id == "doc123"
assert vq.vector is None
@ -384,32 +385,52 @@ class TestVectorQuery:
def test_init_with_valid_vector(self):
vec = [0.1, 0.2, 0.3]
param = HnswQueryParam(ef=300)
vq = VectorQuery(field_name="embedding", vector=vec, param=param)
vq = Query(field_name="embedding", vector=vec, param=param)
assert vq.field_name == "embedding"
assert vq.vector == vec
assert vq.param == param
def test_init_both_id_and_vector_raises_error(self):
with pytest.raises(ValueError):
VectorQuery(field_name="embedding", id="doc123", vector=[0.1])._validate()
Query(field_name="embedding", id="doc123", vector=[0.1])._validate()
def test_init_without_field_name_raises_error(self):
with pytest.raises(ValueError):
VectorQuery(field_name=None)._validate()
Query(field_name=None)._validate()
def test_has_id_returns_true_when_id_set(self):
vq = VectorQuery(field_name="embedding", id="doc123")
vq = Query(field_name="embedding", id="doc123")
assert vq.has_id()
def test_has_id_returns_false_when_no_id(self):
vq = VectorQuery(field_name="embedding", vector=[0.1])
vq = Query(field_name="embedding", vector=[0.1])
assert not vq.has_id()
def test_has_vector_returns_true_with_non_empty_vector(self):
vq = VectorQuery(field_name="embedding", vector=[0.1])
vq = Query(field_name="embedding", vector=[0.1])
assert vq.has_vector()
def test_validate_fails_on_both_id_and_vector(self):
vq = VectorQuery(field_name="test", id="doc123", vector=[0.1])
vq = Query(field_name="test", id="doc123", vector=[0.1])
with pytest.raises(ValueError):
vq._validate()
class TestVectorQueryDeprecated:
def test_deprecation_warning(self):
import warnings
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
vq = VectorQuery(field_name="embedding", id="doc123")
assert len(w) == 1
assert issubclass(w[0].category, DeprecationWarning)
assert "Query" in str(w[0].message)
def test_isinstance_compatibility(self):
import warnings
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
vq = VectorQuery(field_name="embedding", id="doc123")
assert isinstance(vq, Query)

View File

@ -28,9 +28,16 @@ from zvec.executor.query_executor import (
QueryExecutor,
QueryExecutorFactory,
SingleVectorQueryExecutor,
)
from zvec import (
RrfReRanker,
HnswQueryParam,
CollectionSchema,
VectorSchema,
DataType,
Query,
VectorQuery,
)
from zvec import RrfReRanker, HnswQueryParam, CollectionSchema, VectorSchema, DataType
# ----------------------------
@ -65,16 +72,16 @@ class MockCollectionSchema(CollectionSchema):
# ----------------------------
# VectorQuery Test Case
# ----------------------------
class TestVectorQuery:
class TestQuery:
def test_init(self):
query = VectorQuery(field_name="test_field")
query = Query(field_name="test_field")
assert query.field_name == "test_field"
assert query.id is None
assert query.vector is None
assert query.param is None
param = HnswQueryParam()
query = VectorQuery(
query = Query(
field_name="test_field", id="test_id", vector=[1, 2, 3], param=param
)
assert query.field_name == "test_field"
@ -83,20 +90,20 @@ class TestVectorQuery:
assert query.param == param
def test_has_id(self):
query = VectorQuery(field_name="test_field")
query = Query(field_name="test_field")
assert not query.has_id()
query = VectorQuery(field_name="test_field", id="test_id")
query = Query(field_name="test_field", id="test_id")
assert query.has_id()
def test_has_vector(self):
query = VectorQuery(field_name="test_field")
query = Query(field_name="test_field")
assert not query.has_vector()
query = VectorQuery(field_name="test_field", vector=[])
query = Query(field_name="test_field", vector=[])
assert not query.has_vector()
query = VectorQuery(field_name="test_field", vector=[1, 2, 3])
query = Query(field_name="test_field", vector=[1, 2, 3])
assert query.has_vector()
def test_validate_dense_fp16_convert(self):
@ -150,6 +157,26 @@ class TestVectorQuery:
assert math.isclose(np.float16(vec[k]), ret[k], abs_tol=1e-6)
class TestVectorQueryDeprecated:
def test_deprecation_warning(self):
import warnings
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
vq = VectorQuery(field_name="test_field")
assert len(w) == 1
assert issubclass(w[0].category, DeprecationWarning)
assert "Query" in str(w[0].message)
def test_isinstance_compatibility(self):
import warnings
with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
vq = VectorQuery(field_name="test_field")
assert isinstance(vq, Query)
class TestQueryContext:
def test_init(self):
ctx = QueryContext(topk=10)
@ -162,7 +189,7 @@ class TestQueryContext:
assert ctx.core_vectors == []
def test_properties(self):
queries = [VectorQuery(field_name="test")]
queries = [Query(field_name="test")]
reranker = RrfReRanker()
output_fields = ["field1", "field2"]
@ -198,7 +225,7 @@ class TestNoVectorQueryExecutor:
def test_do_validate_with_queries(self):
schema = MockCollectionSchema()
executor = NoVectorQueryExecutor(schema)
ctx = QueryContext(topk=10, queries=[VectorQuery(field_name="test")])
ctx = QueryContext(topk=10, queries=[Query(field_name="test")])
with pytest.raises(
ValueError, match="Collection does not support query with vector or id"
@ -232,7 +259,7 @@ class TestSingleVectorQueryExecutor:
def test_do_validate_multiple_queries(self):
schema = MockCollectionSchema()
executor = SingleVectorQueryExecutor(schema)
queries = [VectorQuery(field_name="test1"), VectorQuery(field_name="test2")]
queries = [Query(field_name="test1"), Query(field_name="test2")]
ctx = QueryContext(topk=10, queries=queries)
with pytest.raises(
@ -260,7 +287,7 @@ class TestMultiVectorQueryExecutor:
def test_do_validate_multiple_queries_without_reranker(self):
schema = MockCollectionSchema()
executor = MultiVectorQueryExecutor(schema)
queries = [VectorQuery(field_name="test1"), VectorQuery(field_name="test2")]
queries = [Query(field_name="test1"), Query(field_name="test2")]
ctx = QueryContext(topk=10, queries=queries)
with pytest.raises(
@ -271,7 +298,7 @@ class TestMultiVectorQueryExecutor:
def test_do_validate_multiple_queries_with_reranker(self):
schema = MockCollectionSchema()
executor = MultiVectorQueryExecutor(schema)
queries = [VectorQuery(field_name="test1"), VectorQuery(field_name="test2")]
queries = [Query(field_name="test1"), Query(field_name="test2")]
reranker = RrfReRanker()
ctx = QueryContext(topk=10, queries=queries, reranker=reranker)

View File

@ -73,7 +73,7 @@ from .model.param import (
VamanaIndexParam,
VamanaQueryParam,
)
from .model.param.vector_query import VectorQuery
from .model.param.query import Query, VectorQuery
# —— Schema & field definitions ——
from .model.schema import CollectionSchema, CollectionStats, FieldSchema, VectorSchema
@ -110,6 +110,7 @@ __all__ = [
"VectorSchema",
"CollectionStats",
# Parameters
"Query",
"VectorQuery",
"InvertIndexParam",
"HnswIndexParam",

View File

@ -29,7 +29,7 @@ from .model.param import (
VamanaIndexParam,
VamanaQueryParam,
)
from .model.param.vector_query import VectorQuery
from .model.param.query import Query, VectorQuery
from .model.schema import CollectionSchema, CollectionStats, FieldSchema, VectorSchema
from .tool import require_module
from .typing import (
@ -70,6 +70,7 @@ __all__: list = [
"MetricType",
"OptimizeOption",
"QuantizeType",
"Query",
"ReRanker",
"ReRanker",
"RrfReRanker",

View File

@ -25,7 +25,7 @@ from _zvec.param import _VectorQuery
from ..extension import ReRanker, RrfReRanker, WeightedReRanker
from ..model.convert import convert_to_py_doc
from ..model.doc import Doc
from ..model.param.vector_query import VectorQuery
from ..model.param.query import Query
from ..model.schema import CollectionSchema
from ..typing import DataType
@ -66,7 +66,7 @@ class QueryContext:
topk: int,
filter: Optional[str] = None,
include_vector: bool = False,
queries: Optional[list[VectorQuery]] = None,
queries: Optional[list[Query]] = None,
output_fields: Optional[list[str]] = None,
reranker: Optional[ReRanker] = None,
):
@ -142,7 +142,7 @@ class QueryExecutor(ABC):
return core_vector
def _do_build_query_with_vector(
self, ctx: QueryContext, query: VectorQuery, collection: _Collection
self, ctx: QueryContext, query: Query, collection: _Collection
) -> _VectorQuery:
core_vector = self._do_build_query_wo_vector(ctx)
core_vector.field_name = query.field_name

View File

@ -15,8 +15,15 @@ from __future__ import annotations
from .collection import Collection
from .doc import Doc
from .param.vector_query import VectorQuery
from .param.query import Query, VectorQuery
from .schema.collection_schema import CollectionSchema
from .schema.field_schema import FieldSchema
__all__ = ["Collection", "CollectionSchema", "Doc", "FieldSchema", "VectorQuery"]
__all__ = [
"Collection",
"CollectionSchema",
"Doc",
"FieldSchema",
"Query",
"VectorQuery",
]

View File

@ -13,6 +13,7 @@
# limitations under the License.
from __future__ import annotations
import warnings
from typing import Optional, Union, overload
from _zvec import _Collection
@ -34,7 +35,7 @@ from .param import (
IVFIndexParam,
OptimizeOption,
)
from .param.vector_query import VectorQuery
from .param.query import Query
from .schema import CollectionSchema, CollectionStats, FieldSchema
__all__ = ["Collection"]
@ -357,8 +358,9 @@ class Collection:
def query(
self,
vectors: Optional[Union[VectorQuery, list[VectorQuery]]] = None,
queries: Optional[Union[Query, list[Query]]] = None,
*,
vectors: Optional[Union[Query, list[Query]]] = None,
topk: int = 10,
filter: Optional[str] = None,
include_vector: bool = False,
@ -367,11 +369,13 @@ class Collection:
) -> list[Doc]:
"""Perform vector similarity search with optional filtering and re-ranking.
At least one `VectorQuery` must be provided.
At least one `Query` must be provided via `queries`.
Args:
vectors (Optional[Union[VectorQuery, list[VectorQuery]]], optional):
queries (Optional[Union[Query, list[Query]]], optional):
One or more vector queries. Defaults to None.
vectors (Optional[Union[Query, list[Query]]], optional):
Deprecated. Use `queries` instead.
topk (int, optional): Number of nearest neighbors to return.
Defaults to 10.
filter (Optional[str], optional): Boolean expression to pre-filter candidates.
@ -387,18 +391,29 @@ class Collection:
list[Doc]: Top-k matching documents, sorted by relevance score.
Examples:
>>> from zvec import VectorQuery
>>> from zvec import Query
>>> results = collection.query(
... vectors=VectorQuery("embedding", vector=[0.1, 0.2]),
... queries=Query(field_name="embedding", vector=[0.1, 0.2]),
... topk=5,
... filter="category == 'tech'",
... output_fields=["title", "url"]
... )
"""
if vectors is not None:
warnings.warn(
"The 'vectors' parameter is deprecated and will be removed in a future version. "
"Use 'queries' instead.",
DeprecationWarning,
stacklevel=2,
)
if queries is not None:
raise ValueError("Cannot specify both 'queries' and 'vectors'.")
queries = vectors
ctx = QueryContext(
topk=topk,
filter=filter,
queries=[vectors] if isinstance(vectors, VectorQuery) else vectors,
queries=[queries] if isinstance(queries, Query) else queries,
include_vector=include_vector,
output_fields=output_fields,
reranker=reranker,

View File

@ -13,20 +13,21 @@
# limitations under the License.
from __future__ import annotations
import warnings
from dataclasses import dataclass
from typing import Optional, Union
from ...common import VectorType
from . import HnswQueryParam, HnswRabitqQueryParam, IVFQueryParam
__all__ = ["VectorQuery"]
__all__ = ["Query", "VectorQuery"]
@dataclass(frozen=True)
class VectorQuery:
"""Represents a vector search query for a specific field in a collection.
class Query:
"""Represents a search query for a specific field in a collection.
A `VectorQuery` can be constructed using either a document ID (to look up
A `Query` can be constructed using either a document ID (to look up
its vector) or an explicit vector. It may optionally include index-specific
query parameters to control search behavior (e.g., `ef` for HNSW, `nprobe` for IVF).
@ -34,7 +35,7 @@ class VectorQuery:
behavior is implementation-defined (typically `id` takes precedence).
Attributes:
field_name (str): Name of the vector field to query.
field_name (str): Name of the field to query.
id (Optional[str], optional): Document ID to fetch vector from. Default is None.
vector (VectorType, optional): Explicit query vector. Default is None.
param (Optional[Union[HnswQueryParam, IVFQueryParam]], optional):
@ -43,9 +44,9 @@ class VectorQuery:
Examples:
>>> import zvec
>>> # Query by ID
>>> q1 = zvec.VectorQuery(field_name="embedding", id="doc123")
>>> q1 = zvec.Query(field_name="embedding", id="doc123")
>>> # Query by vector
>>> q2 = zvec.VectorQuery(
>>> q2 = zvec.Query(
... field_name="embedding",
... vector=[0.1, 0.2, 0.3],
... param=HnswQueryParam(ef=300)
@ -78,3 +79,16 @@ class VectorQuery:
raise ValueError("Field name cannot be empty")
if self.id and self.vector:
raise ValueError("Cannot provide both id and vector")
class VectorQuery(Query):
"""Deprecated alias for Query. Use Query instead."""
def __new__(cls, *args, **kwargs): # noqa : ARG004
warnings.warn(
"VectorQuery is deprecated and will be removed in a future version. "
"Use Query instead.",
DeprecationWarning,
stacklevel=2,
)
return super().__new__(cls)