Files
alibaba--zvec/python/tests/test_doc.py
T
2026-07-13 12:47:42 +08:00

270 lines
10 KiB
Python

# Copyright 2025-present the zvec project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations
import math
import pytest
from zvec._zvec import _Doc
from zvec import FieldSchema, VectorSchema, Doc, DataType
# ----------------------------
# PyDoc Test Case
# ----------------------------
class TestPyDoc:
def test_default(self):
Doc(id="1")
def test_with_single_vector(self):
doc = Doc(id="1", vectors={"dense": [1, 2, 3]})
assert doc is not None
assert doc.id == "1"
assert doc.vector("dense") == [1, 2, 3]
def test_with_hybrid_vectors(self):
doc = Doc(
id="1", vectors={"dense": [1, 2, 3], "sparse": {1: 1.0, 2: 2.0, 3: 3.0}}
)
assert doc is not None
assert doc.id == "1"
assert doc.vector("dense") == [1, 2, 3]
assert doc.vector("sparse") == {1: 1.0, 2: 2.0, 3: 3.0}
def test_with_multi_vectors(self):
doc = Doc(
id="1",
vectors={
"image": [1, 2, 3],
"description": [4, 5, 6],
"keys": {1: 1.0, 2: 2.0, 3: 3.0},
},
fields={"author": "Tom", "age": 19, "is_male": True, "weight": 60.5},
)
assert doc is not None
assert doc.id == "1"
assert doc.vector("image") == [1, 2, 3]
assert doc.vector("description") == [4, 5, 6]
assert doc.vector("keys") == {1: 1.0, 2: 2.0, 3: 3.0}
assert doc.field("author") == "Tom"
assert doc.field("age") == 19
assert doc.field("is_male") == True
assert doc.field("weight") == 60.5
def test_with_numpy_array(self):
import numpy as np
doc = Doc._from_tuple(
(
"1",
0.0,
None,
{
"image": np.array([1, 2, 3]),
"description": np.random.random(512),
"keys": {1: 1.0, 2: 2.0, 3: 3.0},
},
)
)
assert doc is not None
assert doc.id == "1"
assert doc.vector("image") == [1, 2, 3]
assert doc.vector("keys") == {1: 1.0, 2: 2.0, 3: 3.0}
# ----------------------------
# CppDoc Test Case
# ----------------------------
class TestCppDoc:
def test_default(self):
doc = _Doc()
assert doc is not None
def test_doc_set_pk(self):
doc = _Doc()
doc.set_pk("1")
assert doc.pk() == "1"
def test_doc_set_score(self):
doc = _Doc()
doc.set_score(0.9)
assert math.isclose(doc.score(), 0.9, rel_tol=1e-6)
def test_doc_get_null_field(self):
doc = _Doc()
schema = FieldSchema("author", DataType.STRING, nullable=True)
doc.set_any("author", schema._get_object(), None)
assert doc.has_field("author")
assert doc.get_any("author", schema.data_type) is None
def test_doc_get_set_has_null_field(self):
doc = _Doc()
schema = FieldSchema("author", DataType.STRING, nullable=False)
with pytest.raises(ValueError):
doc.set_any("author", schema._get_object(), None)
def test_doc_get_set_has_string_field(self):
doc = _Doc()
schema = FieldSchema("author", DataType.STRING)
doc.set_any("author", schema._get_object(), "Tom")
assert doc.has_field("author")
assert doc.get_any("author", DataType.STRING) == "Tom"
def test_doc_get_set_has_bool_field(self):
doc = _Doc()
schema = FieldSchema("is_male", DataType.BOOL)
doc.set_any("is_male", schema._get_object(), True)
assert doc.has_field("is_male")
assert doc.get_any("is_male", DataType.BOOL) == True
def test_doc_get_set_has_int32_field(self):
doc = _Doc()
schema = FieldSchema("age", DataType.INT32)
doc.set_any("age", schema._get_object(), 19)
assert doc.has_field("age")
assert doc.get_any("age", DataType.INT32) == 19
def test_doc_get_set_has_int64_field(self):
doc = _Doc()
schema = FieldSchema("id", DataType.INT64)
doc.set_any("id", schema._get_object(), 1111111111111111111)
assert doc.has_field("id")
assert doc.get_any("id", DataType.INT64) == 1111111111111111111
def test_doc_get_set_has_float_field(self):
doc = _Doc()
schema = FieldSchema("weight", DataType.FLOAT)
doc.set_any("weight", schema._get_object(), 60.5)
assert doc.has_field("weight")
assert math.isclose(doc.get_any("weight", DataType.FLOAT), 60.5, rel_tol=1e-6)
def test_doc_get_set_has_double_field(self):
doc = _Doc()
schema = FieldSchema("height", DataType.DOUBLE)
doc.set_any("height", schema._get_object(), 1.77777777777)
assert doc.has_field("height")
assert math.isclose(
doc.get_any("height", DataType.DOUBLE), 1.7777777777, rel_tol=1e-9
)
def test_doc_get_set_has_uint32_field(self):
doc = _Doc()
schema = FieldSchema("id", DataType.UINT32)
doc.set_any("id", schema._get_object(), 4294967295)
assert doc.has_field("id")
assert doc.get_any("id", DataType.UINT32) == 4294967295
def test_doc_get_set_has_uint64_field(self):
doc = _Doc()
schema = FieldSchema("id", DataType.UINT64)
doc.set_any("id", schema._get_object(), 18446744073709551615)
assert doc.has_field("id")
assert doc.get_any("id", DataType.UINT64) == 18446744073709551615
def test_doc_get_set_has_array_string_field(self):
doc = _Doc()
schema = FieldSchema("tags", DataType.ARRAY_STRING)
doc.set_any("tags", schema._get_object(), ["tag1", "tag2", "tag3"])
assert doc.has_field("tags")
assert doc.get_any("tags", DataType.ARRAY_STRING) == ["tag1", "tag2", "tag3"]
def test_doc_get_set_has_array_int32_field(self):
doc = _Doc()
schema = FieldSchema("ids", DataType.ARRAY_INT32)
doc.set_any("ids", schema._get_object(), [1, 2, 3])
assert doc.has_field("ids")
assert doc.get_any("ids", DataType.ARRAY_INT32) == [1, 2, 3]
def test_doc_get_set_has_array_int64_field(self):
doc = _Doc()
schema = FieldSchema("ids", DataType.ARRAY_INT64)
doc.set_any("ids", schema._get_object(), [1, 2, 3])
assert doc.has_field("ids")
assert doc.get_any("ids", DataType.ARRAY_INT64) == [1, 2, 3]
def test_doc_get_set_has_array_float_field(self):
doc = _Doc()
schema = FieldSchema("weights", DataType.ARRAY_FLOAT)
doc.set_any("weights", schema._get_object(), [1.0, 2.0, 3.0])
assert doc.has_field("weights")
assert doc.get_any("weights", DataType.ARRAY_FLOAT) == [1.0, 2.0, 3.0]
def test_doc_get_set_has_array_double_field(self):
doc = _Doc()
schema = FieldSchema("heights", DataType.ARRAY_DOUBLE)
doc.set_any("heights", schema._get_object(), [1.0, 2.0, 3.0])
assert doc.has_field("heights")
assert doc.get_any("heights", DataType.ARRAY_DOUBLE) == [1.0, 2.0, 3.0]
def test_doc_get_set_has_array_bool_field(self):
doc = _Doc()
schema = FieldSchema("bools", DataType.ARRAY_BOOL)
doc.set_any("bools", schema._get_object(), [True, False, True])
assert doc.has_field("bools")
assert doc.get_any("bools", DataType.ARRAY_BOOL) == [True, False, True]
def test_doc_get_set_has_vector_fp16(self):
doc = _Doc()
schema = VectorSchema("image", DataType.VECTOR_FP16)
doc.set_any("image", schema._get_object(), [1.0, 2.0, 3.0])
assert doc.has_field("image")
image_vector = doc.get_any("image", DataType.VECTOR_FP16)
assert image_vector is not None
for i in range(len(image_vector)):
assert math.isclose(image_vector[i], [1.0, 2.0, 3.0][i], rel_tol=1e-6)
def test_doc_get_set_has_vector_fp32(self):
doc = _Doc()
schema = VectorSchema("image", DataType.VECTOR_FP32)
doc.set_any("image", schema._get_object(), [1.111111, 2.222222, 3.333333])
assert doc.has_field("image")
vector = doc.get_any("image", DataType.VECTOR_FP32)
assert vector is not None
for i in range(len(vector)):
assert math.isclose(
vector[i], [1.111111, 2.222222, 3.333333][i], rel_tol=1e-6
)
def test_doc_get_set_has_vector_int8(self):
doc = _Doc()
schema = VectorSchema("image", DataType.VECTOR_INT8)
doc.set_any("image", schema._get_object(), [1, 2, 3])
assert doc.has_field("image")
assert doc.get_any("image", DataType.VECTOR_INT8) == [1, 2, 3]
def test_doc_get_set_has_sparse_vector_fp32(self):
doc = _Doc()
sparse = {1: 1.111111, 2: 2.222222, 3: 3.333333}
schema = VectorSchema("key", DataType.SPARSE_VECTOR_FP32)
doc.set_any("key", schema._get_object(), sparse)
assert doc.has_field("key")
vector = doc.get_any("key", DataType.SPARSE_VECTOR_FP32)
assert vector is not None
assert isinstance(vector, dict)
for key, value in sparse.items():
assert math.isclose(vector[key], value, rel_tol=1e-6)
def test_doc_get_set_has_sparse_vector_fp16(self):
doc = _Doc()
sparse = {1: 1.1, 2: 2.2, 3: 3.3}
schema = VectorSchema("key", DataType.SPARSE_VECTOR_FP16)
doc.set_any("key", schema._get_object(), sparse)
assert doc.has_field("key")
vector = doc.get_any("key", DataType.SPARSE_VECTOR_FP16)
assert vector is not None
assert isinstance(vector, dict)
for key, value in sparse.items():
assert math.isclose(vector[key], value, rel_tol=1e-1)