test: [cp2.6] Update hybrid search tests to milvus client style (#45810)

related issue: https://github.com/milvus-io/milvus/issues/45326
releted pr: #45772 

1. also cp more async tests to 2.6

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
This commit is contained in:
yanliang567 2025-11-25 14:25:07 +08:00 committed by GitHub
parent b92f17b138
commit 428526aa22
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 1124 additions and 1112 deletions

View File

@ -39,6 +39,58 @@ class AsyncMilvusClientWrapper:
check_result = ResponseChecker(res, func_name, check_task, check_items, is_succ, **kwargs).run()
return res, check_result
@logger_interceptor()
async def list_collections(self, timeout: Optional[float] = None, **kwargs):
return await self.async_milvus_client.list_collections(timeout, **kwargs)
@logger_interceptor()
async def has_collection(self, collection_name: str, timeout: Optional[float] = None, **kwargs):
return await self.async_milvus_client.has_collection(collection_name, timeout, **kwargs)
@logger_interceptor()
async def has_partition(self, collection_name: str, partition_name: str, timeout: Optional[float] = None, **kwargs):
return await self.async_milvus_client.has_partition(collection_name, partition_name, timeout, **kwargs)
@logger_interceptor()
async def describe_collection(self, collection_name: str, timeout: Optional[float] = None, **kwargs):
return await self.async_milvus_client.describe_collection(collection_name, timeout, **kwargs)
@logger_interceptor()
async def list_partitions(self, collection_name: str, timeout: Optional[float] = None, **kwargs):
return await self.async_milvus_client.list_partitions(collection_name, timeout, **kwargs)
@logger_interceptor()
async def get_collection_stats(self, collection_name: str, timeout: Optional[float] = None, **kwargs):
return await self.async_milvus_client.get_collection_stats(collection_name, timeout, **kwargs)
@logger_interceptor()
async def flush(self, collection_name: str, timeout: Optional[float] = None, **kwargs):
return await self.async_milvus_client.flush(collection_name, timeout, **kwargs)
@logger_interceptor()
async def get_load_state(self, collection_name: str, timeout: Optional[float] = None, **kwargs):
return await self.async_milvus_client.get_load_state(collection_name, timeout, **kwargs)
@logger_interceptor()
async def describe_index(self, collection_name: str, index_name: str, timeout: Optional[float] = None, **kwargs):
return await self.async_milvus_client.describe_index(collection_name, index_name, timeout, **kwargs)
@logger_interceptor()
async def create_database(self, db_name: str, timeout: Optional[float] = None, **kwargs):
return await self.async_milvus_client.create_database(db_name, timeout, **kwargs)
@logger_interceptor()
async def drop_database(self, db_name: str, timeout: Optional[float] = None, **kwargs):
return await self.async_milvus_client.drop_database(db_name, timeout, **kwargs)
@logger_interceptor()
async def list_databases(self, timeout: Optional[float] = None, **kwargs):
return await self.async_milvus_client.list_databases(timeout, **kwargs)
@logger_interceptor()
async def list_indexes(self, collection_name: str, field_name: str = "", **kwargs):
return await self.async_milvus_client.list_indexes(collection_name, field_name, **kwargs)
@logger_interceptor()
async def create_collection(self,
collection_name: str,
@ -197,6 +249,11 @@ class AsyncMilvusClientWrapper:
kwargs["check_fields"] = False # do not check fields for now
return CollectionSchema([], **kwargs)
@classmethod
def prepare_index_params(cls, field_name: str = "", **kwargs):
res, check = api_request([AsyncMilvusClient.prepare_index_params, field_name], **kwargs)
return res, check
@logger_interceptor()
async def close(self, **kwargs):
return await self.async_milvus_client.close(**kwargs)

View File

@ -173,7 +173,6 @@ class TestcaseBase(Base):
log.info(f"server version: {server_version}")
return res
def get_tokens_by_analyzer(self, text, analyzer_params):
if cf.param_info.param_uri:
uri = cf.param_info.param_uri

View File

@ -175,19 +175,6 @@ class TestMilvusClientV2Base(Base):
**kwargs).run()
return res, check_result
@trace()
def hybrid_search(self, client, collection_name, reqs, ranker, limit=10, output_fields=None, timeout=None,
check_task=None, check_items=None, **kwargs):
timeout = TIMEOUT if timeout is None else timeout
kwargs.update({"timeout": timeout})
func_name = sys._getframe().f_code.co_name
res, check = api_request([client.hybrid_search, collection_name, reqs, ranker, limit,
output_fields], **kwargs)
check_result = ResponseChecker(res, func_name, check_task, check_items, check,
collection_name=collection_name, reqs=reqs, ranker=ranker, limit=limit,
output_fields=output_fields, **kwargs).run()
return res, check_result
@trace()
def search_iterator(self, client, collection_name, data, batch_size, limit=-1, filter=None, output_fields=None,
@ -210,16 +197,16 @@ class TestMilvusClientV2Base(Base):
return res, check_result
@trace()
def hybrid_search(self, client, collection_name, reqs, rerank, limit=10,
def hybrid_search(self, client, collection_name, reqs, ranker, limit=10,
output_fields=None, timeout=None, partition_names=None,
check_task=None, check_items=None, **kwargs):
timeout = TIMEOUT if timeout is None else timeout
# kwargs.update({"timeout": timeout})
func_name = sys._getframe().f_code.co_name
res, check = api_request([client.hybrid_search, collection_name, reqs, rerank, limit,
res, check = api_request([client.hybrid_search, collection_name, reqs, ranker, limit,
output_fields, timeout, partition_names], **kwargs)
check_result = ResponseChecker(res, func_name, check_task, check_items, check,
collection_name=collection_name, reqs=reqs, rerank=rerank, limit=limit,
collection_name=collection_name, reqs=reqs, ranker=ranker, limit=limit,
output_fields=output_fields, timeout=timeout, partition_names=partition_names, **kwargs).run()
return res, check_result
@ -332,15 +319,6 @@ class TestMilvusClientV2Base(Base):
self.tear_down_collection_names.remove(collection_name)
return res, check_result
@trace()
def list_partitions(self, client, collection_name, check_task=None, check_items=None, **kwargs):
func_name = sys._getframe().f_code.co_name
res, check = api_request([client.list_partitions, collection_name], **kwargs)
check_result = ResponseChecker(res, func_name, check_task, check_items, check,
collection_name=collection_name,
**kwargs).run()
return res, check_result
@trace()
def list_indexes(self, client, collection_name, field_name=None, check_task=None, check_items=None, **kwargs):
func_name = sys._getframe().f_code.co_name
@ -359,16 +337,6 @@ class TestMilvusClientV2Base(Base):
**kwargs).run()
return res, check_result
@trace()
def prepare_index_params(self, client, timeout=None, check_task=None, check_items=None, **kwargs):
timeout = TIMEOUT if timeout is None else timeout
kwargs.update({"timeout": timeout})
func_name = sys._getframe().f_code.co_name
res, check = api_request([client.prepare_index_params], **kwargs)
check_result = ResponseChecker(res, func_name, check_task, check_items, check,
**kwargs).run()
return res, check_result
@trace()
def load_collection(self, client, collection_name, timeout=None, check_task=None, check_items=None, **kwargs):
@ -803,19 +771,6 @@ class TestMilvusClientV2Base(Base):
object_name=object_name, db_name=db_name, **kwargs).run()
return res, check_result
@trace()
def grant_privilege_v2(self, client, role_name, privilege, collection_name, db_name=None,
timeout=None, check_task=None, check_items=None, **kwargs):
timeout = TIMEOUT if timeout is None else timeout
kwargs.update({"timeout": timeout})
func_name = sys._getframe().f_code.co_name
res, check = api_request([client.grant_privilege_v2, role_name, privilege, collection_name,
db_name], **kwargs)
check_result = ResponseChecker(res, func_name, check_task, check_items, check,
role_name=role_name, privilege=privilege,
collection_name=collection_name, db_name=db_name, **kwargs).run()
return res, check_result
@trace()
def revoke_privilege(self, client, role_name, object_type, privilege, object_name, db_name="",
timeout=None, check_task=None, check_items=None, **kwargs):
@ -1082,7 +1037,7 @@ class TestMilvusClientV2Base(Base):
kwargs.update({"timeout": timeout})
func_name = sys._getframe().f_code.co_name
res, check = api_request([client.update_resource_groups, name], **kwargs)
res, check = api_request([client.drop_resource_group, name], **kwargs)
check_result = ResponseChecker(res, func_name, check_task, check_items, check,
name=name, **kwargs).run()
return res, check_result

View File

@ -454,8 +454,8 @@ class ResponseChecker:
else:
ids = list(hits.ids)
distances = list(hits.distances)
if (len(hits) != check_items["limit"]) \
or (len(ids) != check_items["limit"]):
if check_items.get("limit", None) is not None \
and ((len(hits) != check_items["limit"]) or (len(ids) != check_items["limit"])):
log.error("search_results_check: limit(topK) searched (%d) "
"is not equal with expected (%d)"
% (len(hits), check_items["limit"]))

View File

@ -339,20 +339,23 @@ def output_field_value_check(search_res, original, pk_name):
:return: True or False
"""
pk_name = ct.default_primary_field_name if pk_name is None else pk_name
nq = len(search_res)
limit = len(search_res[0])
for i in range(limit):
entity = search_res[0][i].fields
_id = search_res[0][i].id
for field in entity.keys():
if isinstance(entity[field], list):
for order in range(0, len(entity[field]), 4):
assert abs(original[field][_id][order] - entity[field][order]) < ct.epsilon
elif isinstance(entity[field], dict) and field != ct.default_json_field_name:
# sparse checking, sparse vector must be the last, this is a bit hacky,
# but sparse only supports list data type insertion for now
assert entity[field].keys() == original[-1][_id].keys()
else:
num = original[original[pk_name] == _id].index.to_list()[0]
assert original[field][num] == entity[field]
check_nqs = min(2, nq) # the output field values are wrong only at nq>=2 #45338
for n in range(check_nqs):
for i in range(limit):
entity = search_res[n][i].fields
_id = search_res[n][i].id
for field in entity.keys():
if isinstance(entity[field], list):
for order in range(0, len(entity[field]), 4):
assert abs(original[field][_id][order] - entity[field][order]) < ct.epsilon
elif isinstance(entity[field], dict) and field != ct.default_json_field_name:
# sparse checking, sparse vector must be the last, this is a bit hacky,
# but sparse only supports list data type insertion for now
assert entity[field].keys() == original[-1][_id].keys()
else:
num = original[original[pk_name] == _id].index.to_list()[0]
assert original[field][num] == entity[field], f"the output field values are wrong at nq={n}"
return True

View File

@ -1,19 +1,16 @@
import logging
import numpy as np
from common.constants import *
from utils.util_pymilvus import *
from common.common_type import CaseLabel, CheckTasks
from common import common_type as ct
from common import common_func as cf
from utils.util_log import test_log as log
from base.client_v2_base import TestMilvusClientV2Base
from base.client_base import TestcaseBase
import random
import pytest
import pandas as pd
from faker import Faker
import inspect
Faker.seed(19530)
fake_en = Faker("en_US")
@ -1071,3 +1068,44 @@ class TestSearchPaginationIndependent(TestMilvusClientV2Base):
for i in range(ct.default_nq):
assert len(search_res1[i]) == 0, "search result is not empty"
assert len(search_res2[i]) == 0, "search result is not empty"
@pytest.mark.tags(CaseLabel.L2)
def test_search_pagination_flat_index_with_same_score(self):
"""
target: test search pagination with flat index and same score
method:
- create collection in fast mode
- insert data with different pk and same vector
- create flat index
- search with pagination and check the results
expected: the results should be the same as the results of the full search
"""
client = self._client()
collection_name = cf.gen_collection_name_by_testcase_name()
schema, _ = self.create_schema(client)
schema.add_field(default_primary_key_field_name, datatype=DataType.INT64, is_primary=True, auto_id=False)
schema.add_field(default_vector_field_name, datatype=DataType.SPARSE_FLOAT_VECTOR)
schema.add_field(default_float_field_name, datatype=DataType.FLOAT)
self.create_collection(client, collection_name, schema=schema)
vector = cf.gen_vectors(1, ct.default_dim, vector_data_type=DataType.SPARSE_FLOAT_VECTOR)
# insert data with different pk and same vector
nb = 100
data = [{default_primary_key_field_name: i,
default_vector_field_name: vector[0],
default_float_field_name: i * 1.0} for i in range(nb)]
self.insert(client, collection_name, data)
# create flat index
index_params, _ = self.prepare_index_params(client)
index_params.add_index(default_vector_field_name, index_type="SPARSE_INVERTED_INDEX", metric_type="IP")
self.create_index(client, collection_name, index_params=index_params)
self.load_collection(client, collection_name)
# search with pagination and check the results
pages = 10
limit = nb // pages
self.do_search_pagination_and_assert(client, collection_name, limit=limit, pages=pages, dim=default_dim,
vector_dtype=DataType.SPARSE_FLOAT_VECTOR,
index="SPARSE_INVERTED_INDEX", metric_type="IP",
expected_overlap_ratio=50)

View File

@ -1,7 +1,6 @@
[pytest]
addopts = --host localhost --html=/tmp/ci_logs/report.html --self-contained-html -v
addopts = --host localhost --html=/tmp/ci_logs/report.html --self-contained-html -v --log-cli-level INFO
# python3 -W ignore -m pytest
log_format = [%(asctime)s - %(levelname)s - %(name)s]: %(message)s (%(filename)s:%(lineno)s)

View File

@ -50,7 +50,6 @@ class TestAsyncMilvusClientCollectionInvalid(TestMilvusClientV2Base):
method: create collection with invalid collection
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -67,7 +66,6 @@ class TestAsyncMilvusClientCollectionInvalid(TestMilvusClientV2Base):
method: create collection with over max collection name length
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -85,7 +83,6 @@ class TestAsyncMilvusClientCollectionInvalid(TestMilvusClientV2Base):
method: release collection with invalid collection name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -102,7 +99,6 @@ class TestAsyncMilvusClientCollectionInvalid(TestMilvusClientV2Base):
method: release collection with nonexistent name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -119,7 +115,6 @@ class TestAsyncMilvusClientCollectionInvalid(TestMilvusClientV2Base):
method: create collection with over max collection name length
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -128,6 +123,7 @@ class TestAsyncMilvusClientCollectionInvalid(TestMilvusClientV2Base):
error = {ct.err_code: 1100, ct.err_msg: f"the length of a collection name must be less than 255 characters"}
await async_client.release_collection(collection_name, check_task=CheckTasks.err_res, check_items=error)
class TestAsyncMilvusClientCollectionValid(TestMilvusClientV2Base):
""" Test case of collection interface """
@ -145,16 +141,15 @@ class TestAsyncMilvusClientCollectionValid(TestMilvusClientV2Base):
@pytest.mark.tags(CaseLabel.L0)
async def test_async_milvus_client_release_collection_default(self):
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
# 1. create collection
collection_name = cf.gen_unique_str(prefix)
await async_client.create_collection(collection_name, default_dim)
collections = self.list_collections(client)[0]
collections, _ = await async_client.list_collections()
assert collection_name in collections
self.describe_collection(client, collection_name,
desc, _ = await async_client.describe_collection(collection_name,
check_task=CheckTasks.check_describe_collection_property,
check_items={"collection_name": collection_name,
"dim": default_dim,
@ -162,13 +157,13 @@ class TestAsyncMilvusClientCollectionValid(TestMilvusClientV2Base):
# 2. create partition
partition_name = cf.gen_unique_str(partition_prefix)
await async_client.create_partition(collection_name, partition_name)
partitions = self.list_partitions(client, collection_name)[0]
partitions, _ = await async_client.list_partitions(collection_name)
assert partition_name in partitions
# 3. insert
rng = np.random.default_rng(seed=19530)
rows = [{default_primary_key_field_name: i, default_vector_field_name: list(rng.random((1, default_dim))[0]),
default_float_field_name: i * 1.0, default_string_field_name: str(i)} for i in range(default_nb)]
self.insert(client, collection_name, rows)
await async_client.insert(collection_name, rows)
tasks = []
# 4. search
vectors_to_search = rng.random((1, default_dim))
@ -216,9 +211,10 @@ class TestAsyncMilvusClientCollectionValid(TestMilvusClientV2Base):
"pk_name": default_primary_key_field_name})
# 12. drop action
if self.has_partition(client, collection_name, partition_name)[0]:
has_partition, _ = await async_client.has_partition(collection_name, partition_name)
if has_partition:
await async_client.release_partitions(collection_name, partition_name)
await async_client.drop_partition(collection_name, partition_name)
partitions = self.list_partitions(client, collection_name)[0]
partitions, _ = await async_client.list_partitions(collection_name)
assert partition_name not in partitions
await async_client.drop_collection(collection_name)

View File

@ -28,14 +28,13 @@ class TestAsyncMilvusClient(TestMilvusClientV2Base):
@pytest.mark.tags(CaseLabel.L0)
async def test_async_client_default(self):
# init client
milvus_client = self._client()
# init async client
self.init_async_milvus_client()
# create collection
c_name = cf.gen_unique_str(prefix)
await self.async_milvus_client_wrap.create_collection(c_name, dimension=ct.default_dim)
collections, _ = self.list_collections(milvus_client)
collections, _ = await self.async_milvus_client_wrap.list_collections()
assert c_name in collections
# insert entities
@ -118,18 +117,17 @@ class TestAsyncMilvusClient(TestMilvusClientV2Base):
@pytest.mark.tags(CaseLabel.L0)
async def test_async_client_partition(self):
# init client
milvus_client = self._client()
# init async client
self.init_async_milvus_client()
# create collection & partition
c_name = cf.gen_unique_str(prefix)
p_name = cf.gen_unique_str("par")
await self.async_milvus_client_wrap.create_collection(c_name, dimension=ct.default_dim)
collections, _ = self.list_collections(milvus_client)
collections, _ = await self.async_milvus_client_wrap.list_collections()
assert c_name in collections
self.create_partition(milvus_client, c_name, p_name)
partitions, _ = self.list_partitions(milvus_client, c_name)
await self.async_milvus_client_wrap.create_partition(c_name, p_name)
partitions, _ = await self.async_milvus_client_wrap.list_partitions(c_name)
assert p_name in partitions
# insert entities
@ -220,10 +218,9 @@ class TestAsyncMilvusClient(TestMilvusClientV2Base):
await asyncio.gather(*tasks)
@pytest.mark.tags(CaseLabel.L0)
async def test_async_client_with_schema(self, schema):
# init client
async def test_async_client_with_schema(self):
# init async client
pk_field_name = "id"
milvus_client = self._client()
self.init_async_milvus_client()
# create collection
@ -235,7 +232,7 @@ class TestAsyncMilvusClient(TestMilvusClientV2Base):
schema.add_field(ct.default_float_vec_field_name, DataType.FLOAT_VECTOR, dim=ct.default_dim)
schema.add_field(default_vector_name, DataType.FLOAT_VECTOR, dim=ct.default_dim)
await self.async_milvus_client_wrap.create_collection(c_name, schema=schema)
collections, _ = self.list_collections(milvus_client)
collections, _ = await self.async_milvus_client_wrap.list_collections()
assert c_name in collections
# insert entities
@ -258,25 +255,28 @@ class TestAsyncMilvusClient(TestMilvusClientV2Base):
assert r[0]['insert_count'] == step
# flush
# TODO: call async flush() as https://github.com/milvus-io/pymilvus/issues/3060 fixed
# await self.async_milvus_client_wrap.flush(c_name)
milvus_client = self._client()
self.flush(milvus_client, c_name)
stats, _ = self.get_collection_stats(milvus_client, c_name)
stats, _ = await self.async_milvus_client_wrap.get_collection_stats(c_name)
assert stats["row_count"] == async_default_nb
# create index -> load
index_params, _ = self.prepare_index_params(milvus_client,
field_name=ct.default_float_vec_field_name,
index_type="HNSW", metric_type="COSINE", M=30,
efConstruction=200)
index_params = self.async_milvus_client_wrap.prepare_index_params()[0]
index_params.add_index(field_name=ct.default_float_vec_field_name,
index_type="HNSW", metric_type="COSINE", M=30,
efConstruction=200)
index_params.add_index(field_name=default_vector_name, index_type="IVF_SQ8",
metric_type="L2", nlist=32)
await self.async_milvus_client_wrap.create_index(c_name, index_params)
await self.async_milvus_client_wrap.load_collection(c_name)
_index, _ = self.describe_index(milvus_client, c_name, default_vector_name)
_index, _ = await self.async_milvus_client_wrap.describe_index(c_name, default_vector_name)
assert _index["indexed_rows"] == async_default_nb
assert _index["state"] == "Finished"
_load, _ = self.get_load_state(milvus_client, c_name)
assert _load["state"] == LoadState.Loaded
_load, _ = await self.async_milvus_client_wrap.get_load_state(c_name)
assert _load == LoadState.Loaded
# dql tasks
tasks = []
@ -328,14 +328,13 @@ class TestAsyncMilvusClient(TestMilvusClientV2Base):
@pytest.mark.tags(CaseLabel.L0)
async def test_async_client_dml(self):
# init client
milvus_client = self._client()
# init async client
self.init_async_milvus_client()
# create collection
c_name = cf.gen_unique_str(prefix)
await self.async_milvus_client_wrap.create_collection(c_name, dimension=ct.default_dim)
collections, _ = self.list_collections(milvus_client)
collections, _ = await self.async_milvus_client_wrap.list_collections()
assert c_name in collections
# insert entities
@ -385,19 +384,18 @@ class TestAsyncMilvusClient(TestMilvusClientV2Base):
@pytest.mark.tags(CaseLabel.L2)
async def test_async_client_with_db(self):
# init client
milvus_client = self._client()
# init async client
self.init_async_milvus_client()
db_name = cf.gen_unique_str("db")
self.create_database(milvus_client, db_name)
self.close(milvus_client)
await self.async_milvus_client_wrap.create_database(db_name)
await self.async_milvus_client_wrap.close()
uri = cf.param_info.param_uri or f"http://{cf.param_info.param_host}:{cf.param_info.param_port}"
milvus_client, _ = self.connection_wrap.MilvusClient(uri=uri, db_name=db_name)
self.async_milvus_client_wrap.init_async_client(uri, db_name=db_name)
self.async_milvus_client_wrap.init_async_client(uri, token=cf.param_info.param_token, db_name=db_name)
# create collection
c_name = cf.gen_unique_str(prefix)
await self.async_milvus_client_wrap.create_collection(c_name, dimension=ct.default_dim)
collections, _ = self.list_collections(milvus_client)
collections, _ = await self.async_milvus_client_wrap.list_collections()
assert c_name in collections
# insert entities
@ -452,7 +450,7 @@ class TestAsyncMilvusClient(TestMilvusClientV2Base):
async def test_async_client_close(self):
# init async client
uri = cf.param_info.param_uri or f"http://{cf.param_info.param_host}:{cf.param_info.param_port}"
self.async_milvus_client_wrap.init_async_client(uri)
self.async_milvus_client_wrap.init_async_client(uri, token=cf.param_info.param_token)
# create collection
c_name = cf.gen_unique_str(prefix)
@ -467,17 +465,15 @@ class TestAsyncMilvusClient(TestMilvusClientV2Base):
@pytest.mark.tags(CaseLabel.L3)
@pytest.mark.skip("connect with zilliz cloud")
async def test_async_client_with_token(self):
# init client
milvus_client = self._client()
# init async client
uri = cf.param_info.param_uri or f"http://{cf.param_info.param_host}:{cf.param_info.param_port}"
token = cf.param_info.param_token
milvus_client, _ = self.connection_wrap.MilvusClient(uri=uri, token=token)
self.async_milvus_client_wrap.init_async_client(uri, token=token)
# create collection
c_name = cf.gen_unique_str(prefix)
await self.async_milvus_client_wrap.create_collection(c_name, dimension=ct.default_dim)
collections, _ = self.list_collections(milvus_client)
collections, _ = await self.async_milvus_client_wrap.list_collections()
assert c_name in collections
# insert entities

View File

@ -26,6 +26,7 @@ default_vector_field_name = "vector"
default_float_field_name = ct.default_float_field_name
default_string_field_name = ct.default_string_field_name
class TestAsyncMilvusClientIndexInvalid(TestMilvusClientV2Base):
""" Test case of index interface """
@ -49,7 +50,6 @@ class TestAsyncMilvusClientIndexInvalid(TestMilvusClientV2Base):
method: create index with invalid collection name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -59,7 +59,7 @@ class TestAsyncMilvusClientIndexInvalid(TestMilvusClientV2Base):
await async_client.release_collection(collection_name)
await async_client.drop_index(collection_name, "vector")
# 2. prepare index params
index_params = self.prepare_index_params(client)[0]
index_params = async_client.prepare_index_params()[0]
index_params.add_index(field_name="vector")
# 3. create index
error = {ct.err_code: 1100, ct.err_msg: f"Invalid collection name: {name}. the first character of a collection "
@ -78,7 +78,6 @@ class TestAsyncMilvusClientIndexInvalid(TestMilvusClientV2Base):
method: create index with over max collection name length
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -88,7 +87,7 @@ class TestAsyncMilvusClientIndexInvalid(TestMilvusClientV2Base):
await async_client.release_collection(collection_name)
await async_client.drop_index(collection_name, "vector")
# 2. prepare index params
index_params = self.prepare_index_params(client)[0]
index_params = async_client.prepare_index_params()[0]
index_params.add_index(field_name="vector")
# 3. create index
error = {ct.err_code: 1100, ct.err_msg: f"Invalid collection name: {name}. the length of a collection name "
@ -106,7 +105,6 @@ class TestAsyncMilvusClientIndexInvalid(TestMilvusClientV2Base):
method: create index with nonexistent collection name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -117,7 +115,7 @@ class TestAsyncMilvusClientIndexInvalid(TestMilvusClientV2Base):
await async_client.release_collection(collection_name)
await async_client.drop_index(collection_name, "vector")
# 2. prepare index params
index_params = self.prepare_index_params(client)[0]
index_params = async_client.prepare_index_params()[0]
index_params.add_index(field_name="vector")
# 3. create index
error = {ct.err_code: 100,
@ -136,7 +134,6 @@ class TestAsyncMilvusClientIndexInvalid(TestMilvusClientV2Base):
method: create index with invalid index type name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -146,7 +143,7 @@ class TestAsyncMilvusClientIndexInvalid(TestMilvusClientV2Base):
await async_client.release_collection(collection_name)
await async_client.drop_index(collection_name, "vector")
# 2. prepare index params
index_params = self.prepare_index_params(client)[0]
index_params = async_client.prepare_index_params()[0]
index_params.add_index(field_name="vector", index_type=index)
# 3. create index
error = {ct.err_code: 1100, ct.err_msg: f"invalid parameter[expected=valid index][actual=invalid index type: {index}"}
@ -165,7 +162,6 @@ class TestAsyncMilvusClientIndexInvalid(TestMilvusClientV2Base):
method: create index with invalid metric type
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -175,7 +171,7 @@ class TestAsyncMilvusClientIndexInvalid(TestMilvusClientV2Base):
await async_client.release_collection(collection_name)
await async_client.drop_index(collection_name, "vector")
# 2. prepare index params
index_params = self.prepare_index_params(client)[0]
index_params = async_client.prepare_index_params()[0]
index_params.add_index(field_name="vector", metric_type=metric)
# 3. create index
error = {ct.err_code: 1100, ct.err_msg: f"float vector index does not support metric type: {metric}: "
@ -194,7 +190,6 @@ class TestAsyncMilvusClientIndexInvalid(TestMilvusClientV2Base):
method: drop index when collection are not released
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -208,6 +203,49 @@ class TestAsyncMilvusClientIndexInvalid(TestMilvusClientV2Base):
# 3. drop action
await async_client.drop_collection(collection_name)
@pytest.mark.tags(CaseLabel.L1)
@pytest.mark.parametrize("name", ["12-s", "12 s", "(mn)", "中文", "%$#"])
async def test_async_milvus_client_drop_index_invalid_collection_name(self, name):
"""
target: test drop index with invalid collection name
method: drop index with invalid collection name
expected: raise exception
"""
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
# 1. create collection
collection_name = cf.gen_unique_str(prefix)
await async_client.create_collection(collection_name, default_dim, consistency_level="Strong")
await async_client.release_collection(collection_name)
# 2. drop index
error = {ct.err_code: 1100, ct.err_msg: f"collection not found[database=default][collection={name}]"}
await async_client.drop_index(name, "vector", check_task=CheckTasks.err_res, check_items=error)
# 3. drop action
await async_client.drop_collection(collection_name)
@pytest.mark.tags(CaseLabel.L1)
@pytest.mark.parametrize("name", ["a".join("a" for i in range(256))])
async def test_async_milvus_client_drop_index_collection_name_over_max_length(self, name):
"""
target: test drop index with over max collection name length
method: drop index with over max collection name length
expected: raise exception
"""
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
# 1. create collection
collection_name = cf.gen_unique_str(prefix)
await async_client.create_collection(collection_name, default_dim, consistency_level="Strong")
await async_client.release_collection(collection_name)
# 2. drop index
error = {ct.err_code: 1100, ct.err_msg: f"collection not found[database=default][collection={name}]"}
await async_client.drop_index(name, "vector", check_task=CheckTasks.err_res, check_items=error)
# 3. drop action
await async_client.drop_collection(collection_name)
class TestAsyncMilvusClientIndexValid(TestMilvusClientV2Base):
""" Test case of index interface """
@ -236,16 +274,15 @@ class TestAsyncMilvusClientIndexValid(TestMilvusClientV2Base):
method: create collection, index; insert; search and query; drop index
expected: search/query successfully; create/drop index successfully
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
# 1. create collection
collection_name = cf.gen_unique_str(prefix)
await async_client.create_collection(collection_name, default_dim)
collections = self.list_collections(client)[0]
collections, _ = await async_client.list_collections()
assert collection_name in collections
self.describe_collection(client, collection_name,
desc, _ = await async_client.describe_collection(collection_name,
check_task=CheckTasks.check_describe_collection_property,
check_items={"collection_name": collection_name,
"dim": default_dim,
@ -253,11 +290,11 @@ class TestAsyncMilvusClientIndexValid(TestMilvusClientV2Base):
await async_client.release_collection(collection_name)
await async_client.drop_index(collection_name, "vector")
res = self.list_indexes(client, collection_name)[0]
res, _ = await async_client.list_indexes(collection_name)
assert res == []
# 2. prepare index params
index_params = self.prepare_index_params(client)[0]
index_params = async_client.prepare_index_params()[0]
index_params.add_index(field_name="vector", index_type=index, metric_type=metric_type, params=params)
# 3. create index
await async_client.create_index(collection_name, index_params)
@ -266,8 +303,8 @@ class TestAsyncMilvusClientIndexValid(TestMilvusClientV2Base):
rng = np.random.default_rng(seed=19530)
rows = [{default_primary_key_field_name: i, default_vector_field_name: list(rng.random((1, default_dim))[0]),
default_float_field_name: i * 1.0, default_string_field_name: str(i)} for i in range(default_nb)]
self.insert(client, collection_name, rows)
self.load_collection(client, collection_name)
await async_client.insert(collection_name, rows)
await async_client.load_collection(collection_name)
tasks = []
# 5. search
@ -293,8 +330,8 @@ class TestAsyncMilvusClientIndexValid(TestMilvusClientV2Base):
# 7. drop index
await async_client.release_collection(collection_name)
await async_client.drop_index(collection_name, "vector")
res = self.list_indexes(client, collection_name)[0]
res, _ = await async_client.list_indexes(collection_name)
assert res == []
# 8. drop action
self.drop_collection(client, collection_name)
await async_client.drop_collection(collection_name)

View File

@ -50,7 +50,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: create partition with invalid collection name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -68,7 +67,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: create partition with collection name over max length 255
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -88,7 +86,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: create partition with nonexistent collection name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -108,14 +105,13 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: create partition with invalid partition name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
collection_name = cf.gen_unique_str(prefix)
# 1. create collection
await async_client.create_collection(collection_name, default_dim)
self.describe_collection(client, collection_name,
desc, _ = await async_client.describe_collection(collection_name,
check_task=CheckTasks.check_describe_collection_property,
check_items={"collection_name": collection_name,
"dim": default_dim,
@ -134,7 +130,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: create partition with partition name over max length 255
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -160,7 +155,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: create partition with wrong partition name format list
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -183,7 +177,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: drop partition with invalid collection name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -201,7 +194,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: drop partition with collection name over max length 255
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -221,7 +213,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: drop partition with nonexistent collection name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -241,7 +232,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: drop partition with invalid partition name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -262,7 +252,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: drop partition with wrong partition name format list
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -285,7 +274,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: load partitions with invalid collection name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -303,7 +291,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: load partitions with nonexistent collection name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -322,7 +309,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: load partitions with collection name over max length 255
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -343,7 +329,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: load partitions with invalid partition name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -364,7 +349,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: load partitions with nonexistent partition name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -386,7 +370,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: load partitions with partition name over max length 255
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -409,7 +392,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: load partitions after drop index
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -436,7 +418,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: release partitions with invalid collection name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -454,7 +435,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: release partitions with collection name over max length 255
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -474,7 +454,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: release partitions with nonexistent collection name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -494,7 +473,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: release partitions with invalid partition name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -515,7 +493,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: release partitions with invalid partition name list
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -537,7 +514,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: release partitions with partition name list empty
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -559,7 +535,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: release partitions with partition name lists not all exists
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -583,7 +558,6 @@ class TestAsyncMilvusClientPartitionInvalid(TestMilvusClientV2Base):
method: release partitions with nonexistent partition name
expected: raise exception
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
@ -626,16 +600,15 @@ class TestAsyncMilvusClientPartitionValid(TestMilvusClientV2Base):
method: 1. create collection, partition 2. insert to partition 3. search and query 4. drop partition, collection
expected: run successfully
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
# 1. create collection
collection_name = cf.gen_unique_str(prefix)
await async_client.create_collection(collection_name, default_dim)
collections = self.list_collections(client)[0]
collections, _ = await async_client.list_collections()
assert collection_name in collections
self.describe_collection(client, collection_name,
desc, _ = await async_client.describe_collection(collection_name,
check_task=CheckTasks.check_describe_collection_property,
check_items={"collection_name": collection_name,
"dim": default_dim,
@ -643,13 +616,13 @@ class TestAsyncMilvusClientPartitionValid(TestMilvusClientV2Base):
# 2. create partition
partition_name = cf.gen_unique_str(partition_prefix)
await async_client.create_partition(collection_name, partition_name)
partitions = self.list_partitions(client, collection_name)[0]
partitions, _ = await async_client.list_partitions(collection_name)
assert partition_name in partitions
# 3. insert
rng = np.random.default_rng(seed=19530)
rows = [{default_primary_key_field_name: i, default_vector_field_name: list(rng.random((1, default_dim))[0]),
default_float_field_name: i * 1.0, default_string_field_name: str(i)} for i in range(default_nb)]
self.insert(client, collection_name, rows, partition_name=partition_name)
await async_client.insert(collection_name, rows, partition_name=partition_name)
tasks = []
# 4. search
vectors_to_search = rng.random((1, default_dim))
@ -672,15 +645,15 @@ class TestAsyncMilvusClientPartitionValid(TestMilvusClientV2Base):
res = await asyncio.gather(*tasks)
# 6. drop action
if self.has_partition(client, collection_name, partition_name)[0]:
has_partition, _ = await async_client.has_partition(collection_name, partition_name)
if has_partition:
await async_client.release_partitions(collection_name, partition_name)
await async_client.drop_partition(collection_name, partition_name)
partitions = self.list_partitions(client, collection_name)[0]
partitions, _ = await async_client.list_partitions(collection_name)
assert partition_name not in partitions
await async_client.drop_collection(collection_name)
@pytest.mark.tags(CaseLabel.L0)
@pytest.mark.skip(reason="blocked by pymilvus issue #2796")
async def test_async_milvus_client_load_release_partitions(self):
"""
target: test load and release partitions normal case
@ -692,16 +665,15 @@ class TestAsyncMilvusClientPartitionValid(TestMilvusClientV2Base):
4. drop partition, collection
expected: run successfully
"""
client = self._client()
self.init_async_milvus_client()
async_client = self.async_milvus_client_wrap
# 1. create collection
collection_name = cf.gen_unique_str(prefix)
await async_client.create_collection(collection_name, default_dim)
collections = self.list_collections(client)[0]
collections, _ = await async_client.list_collections()
assert collection_name in collections
self.describe_collection(client, collection_name,
desc, _ = await async_client.describe_collection(collection_name,
check_task=CheckTasks.check_describe_collection_property,
check_items={"collection_name": collection_name,
"dim": default_dim,
@ -711,20 +683,20 @@ class TestAsyncMilvusClientPartitionValid(TestMilvusClientV2Base):
await async_client.create_partition(collection_name, partition_name_1)
partition_name_2 = cf.gen_unique_str(partition_prefix)
await async_client.create_partition(collection_name, partition_name_2)
partitions = self.list_partitions(client, collection_name)[0]
partitions, _ = await async_client.list_partitions(collection_name)
assert partition_name_1 in partitions
assert partition_name_2 in partitions
# 3. insert
rng = np.random.default_rng(seed=19530)
rows_default = [{default_primary_key_field_name: i, default_vector_field_name: list(rng.random((1, default_dim))[0]),
default_float_field_name: i * 1.0, default_string_field_name: str(i)} for i in range(default_nb)]
self.insert(client, collection_name, rows_default)
await async_client.insert(collection_name, rows_default)
rows_1 = [{default_primary_key_field_name: i, default_vector_field_name: list(rng.random((1, default_dim))[0]),
default_float_field_name: i * 1.0, default_string_field_name: str(i)} for i in range(default_nb, 2 * default_nb)]
self.insert(client, collection_name, rows_1, partition_name=partition_name_1)
await async_client.insert(collection_name, rows_1, partition_name=partition_name_1)
rows_2 = [{default_primary_key_field_name: i, default_vector_field_name: list(rng.random((1, default_dim))[0]),
default_float_field_name: i * 1.0, default_string_field_name: str(i)} for i in range(2 * default_nb, 3 * default_nb)]
self.insert(client, collection_name, rows_2, partition_name=partition_name_2)
await async_client.insert(collection_name, rows_2, partition_name=partition_name_2)
tasks = []
# 4. search and query
vectors_to_search = rng.random((1, default_dim))