SDK 手册
- 1: Python SDK
- 2: C++ SDK
- 3: Java SDK
- 4: Golang SDK
1 - Python SDK
目前只支持python 3.6及以上的版本。
1. 创建客户端
可以创建同步客户端或者异步客户端。
- 同步客户端
from pyproximabe import *
client = Client('127.0.0.1', 16000)
Proxima BE服务支持 GRPC 和 HTTP 两种协议,监听在不同的端口上。同步客户端同时支持这两种协议,默认使用GRPC协议。如果有需求,可以用下面的方式来指定协议。
client = Client('127.0.0.1', 16001, 'http')
- 异步客户端
from pyproximabe import *
client = AsyncClient(HOST, GRPC_PORT)
异步客户端基于asyncio实现,除了需要await结果外,和同步客户端的使用方式完全一致。 异步客户端只支持GRPC协议。
同步或异步客户端支持的参数如下
def __init__(self, host, port=16000, handler='grpc', timeout=10):
参数 | 说明 |
---|---|
host | 服务器地址,str类型 |
port | 服务器端口,int类型 |
handler | 协议类型,str类型,一般不需要指定。 同步客户端支持grpc/http,异步客户端只支持grpc。 |
timeout | 超时时间,单位秒,float类型,默认为10。指定为None则不超时。 |
使用完毕后,可以调用close()
关闭客户端,其参数为空,返回值为None。
client.close()
2. 集合管理
2.1. 集合创建
创建直写集合
collection_name = 'iris'
index_column = IndexColumnParam('length', 4, IndexType.PROXIMA_GRAPH_INDEX)
collection_config = CollectionConfig(collection_name, [index_column], ['iris_type'])
status = client.create_collection(collection_config)
if not status.ok():
# error handling
logging.error('create collection failed, status=%s', status)
首先,创建一个或多个索引列
index_column = IndexColumnParam('length', 4, IndexType.PROXIMA_GRAPH_INDEX)
参数如下
def __init__(self,
name,
dimension,
index_type=IndexType.PROXIMA_GRAPH_INDEX,
data_type=DataType.VECTOR_FP32,
extra_params=None):
参数 | 说明 |
---|---|
name | 索引列名称,str类型。 |
dimension | 向量维度,int类型。 |
index_type | 索引类型,IndexType 类型,默认为PROXIMA_GRAPH_INDEX。 |
data_type | 数据类型,DataType 类型,默认为VECTOR_FP32。 |
extra_params | 扩展参数,dict类型,默认为空。 |
然后,创建CollectionConfig
。
collection_config = CollectionConfig(collection_name, [index_column], ['iris_type'])
(python_collection_config)= 参数如下
def __init__(self,
collection_name,
index_column_params,
forward_column_names=None,
repository_config=None,
max_docs_per_segment=0):
参数 | 说明 |
---|---|
collection_name | 集合名称,str类型。 |
index_column_params | 索引列列表,List[IndexColumnParam]类型。 |
forward_column_names | 正排列列表,List[str]类型。默认为空。 |
repository_config | 仓库配置,DatabaseRepository类型。默认为None。 |
max_docs_per_segment | 每个segment的最大文档数,long类型。默认为0,文档数不限。 |
最后,调用client接口。
status = client.create_collection(collection_config)
if not status.ok():
# error handling
logging.error('create collection failed, status=%s', status)
create_collection()
接收CollectionConfig
参数,返回ProximaBeStatus。
def create_collection(self, collection_config):
创建数据库旁路集合
MYSQL_PORT = 3306
MYSQL_HOST = HOST
mysql_table_name = 'iris_table'
mysql_database_name = 'test_db'
mysql_user='root'
mysql_password='root'
index_column = IndexColumnParam('length', 4, IndexType.PROXIMA_GRAPH_INDEX)
database_repository = DatabaseRepository('test_repository',
f'mysql://{MYSQL_HOST}:{MYSQL_PORT}/{mysql_database_name}',
mysql_table_name, mysql_user, mysql_password)
collection_config = CollectionConfig(collection_name, [index_column], ['iris_type'], database_repository)
status = client.create_collection(collection_config)
除了需要创建DatabaseRepository
外,其他参数和直写集合完全相同。目前只支持mysql。
database_repository = DatabaseRepository('test_repository',
f'mysql://{MYSQL_HOST}:{MYSQL_PORT}/{mysql_database_name}',
mysql_table_name, mysql_user, mysql_password)
参数列表如下
def __init__(self, repository_name, connection_uri, table_name, user, password):
参数 | 说明 |
---|---|
repository_name | 仓库名称,str类型。 |
connection_uri | 数据库连接串,str类型,如"mysql://localhost/database",不包含用户名和密码。 |
table_name | 表名,str类型。 |
user | 用户名,str类型。 |
password | 数据库密码,str类型。 |
2.2. 描述集合
status, collection_info = client.describe_collection(collection_name)
if not status.ok():
pass # error handling
print(collection_info)
describe_collection()
接收str类型的collection_name
def describe_collection(self, collection_name):
返回值有两个
2.3. 获取集合统计信息
status, collection_stats = client.stats_collection(collection_name)
if not status.ok():
pass # error handling
print(collection_stats)
stats_collection()
接收str类型的collection_name
def stats_collection(self, collection_name):
返回值有两个
2.4. 删除集合
status = client.drop_collection(collection_name)
drop_collection()
接收str类型的collection_name
,返回ProximaBeStatus。
def drop_collection(self, collection_name):
2.5. 获取集合列表
status, collections_data = client.list_collections()
list_collections()
参数列表如下
def list_collections(self, repository_name=None):
参数 | 说明 |
---|---|
repository_name | 仓库名称,str类型,默认为空。参数为空时,返回所有的集合列表,否则返回指定仓库下的集合列表。 |
返回值有两个 |
3. 文档管理
3.1. 通用接口
import struct
row_meta = WriteRequest.RowMeta([WriteRequest.IndexColumnMeta('length', 'VECTOR_FP32', 4)],
['iris_type'],
[DataType.STRING])
rows = [
WriteRequest.Row(100001,
WriteRequest.OperationType.INSERT,
[[5.9,3.0,5.1,1.8]],
['Iris-virginica']),
WriteRequest.Row(100002,
WriteRequest.OperationType.INSERT,
['[5.9,3.0,5.1,1.8]'],
['Iris-virginica']),
WriteRequest.Row(10002,
WriteRequest.OperationType.UPDATE,
[struct.pack('<4f', 5.9, 3.0, 5.1, 1.8)],
['Iris-virginica']),
WriteRequest.Row(10003, WriteRequest.OperationType.DELETE),
]
write_request = WriteRequest(collection_name, rows, row_meta)
status = client.write(write_request)
首先,创建WriteRequest.RowMeta
,描述插入行的数据类型等信息。
row_meta = WriteRequest.RowMeta([WriteRequest.IndexColumnMeta('length', 'VECTOR_FP32', 4)],
['iris_type'],
[DataType.STRING])
WriteRequest.IndexColumnMeta
的参数如下
def __init__(self, name, data_type, dimension):
参数 | 说明 |
---|---|
name | 索引列名称,str类型。 |
data_type | 数据类型,DataType 类型。 |
dimension | 向量维度,int类型。 |
WriteRequest.RowMeta 的参数如下 |
def __init__(self,
index_column_metas,
forward_column_names=None,
forward_column_types=None):
参数 | 说明 |
---|---|
index_column_metas | 索引列列表,List[WriteRequest.IndexColumnMeta]类型。 |
forward_column_names | 正排列名称列表,List[str]。默认为空。 |
forward_column_types | 正排列类型列表,List[DataType]。默认为空。 |
然后创建WriteRequest.Row
。
WriteRequest.Row(100001,
WriteRequest.OperationType.INSERT,
[[5.9,3.0,5.1,1.8]],
['Iris-virginica']),
WriteRequest.Row
的参数如下
def __init__(self,
primary_key,
operation_type,
index_column_values=None,
forward_column_values=None,
lsn_context=None):
参数 | 说明 |
---|---|
primary_key | 主键,long类型。 |
operation_type | 操作类型, WriteRequest.OperationType 类型。 |
index_column_values | 索引列的值列表,list类型,operation_type为删除时不需要指定。支持三种类型
|
forward_column_values | 正排列的值列表,list类型。 |
lsn_context | 日志序列号上下文,LsnContext类型,默认为空。一般不需要设置。 |
然后创建WriteRequest |
write_request = WriteRequest(collection_name, rows, row_meta)
WriteRequest参数如下
def __init__(self,
collection_name,
rows,
row_meta=None,
request_id=None,
magic_number=None):
参数 | 说明 |
---|---|
collection_name | 集合名称,str类型。 |
rows | 文档列表,List[WriteRequest.Row]类型。 |
row_meta | 文档元数据,WriteRequest.RowMeta类型。如果所有的operation_type都为DELETE,不需要指定。 |
request_id | 请求id,str类型,默认为空。一般不需要设置。 |
magic_number | 服务端魔数,long类型,默认为0。一般不需要设置。 |
最后调用client接口。
status = client.write(write_request)
write()
接收WriteRequest
参数,返回ProximaBeStatus。
def write(self, write_request):
3.2. 删除接口
status = client.delete_document_by_keys(collection_name, [10001, 10002])
在只需要删除时,python sdk提供了简化接口,只需要指定集合名称和主键列表。 参数如下
def delete_document_by_keys(self, collection_name, primary_keys):
参数 | 说明 |
---|---|
collection_name | 集合名称,str类型。 |
primary_keys | 主键列表,List[long]类型。 |
delete_document_by_keys() 返回值为ProximaBeStatus。 |
4. 文档查询
4.1. 向量查询
status, knn_res = client.query(collection_name,
'length',
[[5.1, 3.5, 1.4, 0.2],
[5.5, 2.3, 4.0, 1.3]],
'VECTOR_FP32',
topk=2)
for i, result in enumerate(knn_res.results):
print(f'Query: {i}')
for doc in result:
forward_values = ','.join(
f'{k}={v}' for k, v in doc.forward_column_values.items())
print(
f' primary_key={doc.primary_key}, score={doc.score}, forward_column_values=[{forward_values}]'
)
query()
的参数如下
def query(self,
collection_name,
column_name,
features,
data_type=None,
dimension=None,
batch_count=None,
topk=100,
is_linear=False,
radius=None,
extra_params=None):
参数 | 说明 |
---|---|
collection_name | 集合名称,str类型。 |
column_name | 索引列名称,str类型。 |
features | 特征,支持三种类型
|
data_type | 数据类型,DataType 类型。默认为空。
|
dimension | 向量维度,int类型。默认为空。
|
batch_count | batch大小,int类型。默认为空。
|
topk | 单条查询向量返回的结果数,int类型。默认为100。 |
is_linear | 是否做线性查找,bool类型。默认为False,基于索引做查找。 |
radius | 搜索半径,只返回以搜索向量为球心的球体内的向量,float类型。默认为0.0,搜索半径不限。 |
extra_params | 扩展参数,dict类型。 |
返回值有两个 |
4.2. 主键查询
status, res = client.get_document_by_key(collection_name, primary_key=100001)
get_document_by_key()
的参数如下
def get_document_by_key(self, collection_name, primary_key):
参数 | 说明 |
---|---|
collection_name | 集合名称,str类型。 |
primary_key | 主键,long类型。 |
返回值有两个 |
- ProximaBeStatus。主键不存在时,status.ok() == True.
- Document。主键不存在时,返回None。
5. 错误处理
错误处理
python sdk接口一般会返回ProximaBeStatus
类型,其包含两个属性
属性 | 说明 |
---|---|
code | 错误码,int类型。 |
reason | 错误详情,str类型。 |
可以通过ok()
接口来判断是否成功。
def ok(self):
return self.code == 0
:class: warning
请求服务端成功时才会返回ProximaBeStatus,如果客户端参数检查失败或者网络有问题,会抛出ProximaSeException异常。
class ProximaSeException(Exception):
pass
6. 类型定义
IndexType
class IndexType(IntEnum):
UNDEFINED = 0
PROXIMA_GRAPH_INDEX = 1
DataType
class DataType(IntEnum):
UNDEFINED = 0
BINARY = 1
STRING = 2
BOOL = 3
INT32 = 4
INT64 = 5
UINT32 = 6
UINT64 = 7
FLOAT = 8
DOUBLE = 9
VECTOR_BINARY32 = 20
VECTOR_BINARY64 = 21
VECTOR_FP16 = 22
VECTOR_FP32 = 23
VECTOR_FP64 = 24
VECTOR_INT4 = 25
VECTOR_INT8 = 26
VECTOR_INT16 = 27
WriteRequest.OperationType
class OperationType(IntEnum):
INSERT = 0
UPDATE = 1
DELETE = 2
Document
Document
包含以下属性
属性 | 说明 |
---|---|
primary_key | 主键,long类型。 |
score | 分值,即距离查询向量的距离,float类型。 |
forward_column_values | 正排名称到值的映射,dict类型。 |
QueryResponse
QueryResponse
包含以下属性
属性 | 说明 |
---|---|
results | 结果列表,List[List[Document]]类型。第一重list表示多个查询向量的结果,第二重list表示每个向量的Document列表 |
debug_info | 服务端调试信息,str类型。 |
latency_us | 服务端统计的耗时,单位为微秒。 |
CollectionInfo
CollectionInfo
包含以下属性
属性 | 说明 |
---|---|
collection_config | 集合配置, CollectionConfig类型。 |
status | 集合状态,CollectionInfo.Status 类型。 |
uuid | 集合唯一标识,str类型。 |
latest_lsn_context | 最新日志序列号上下文, LsnContext 类型。 |
magic_number | 服务端魔数,long类型。 |
{ref}CollectionConfig定义见这里<python_collection_config>
CollectionInfo.Status
定义
class Status(IntEnum):
"""Collection Status"""
INITIALIZED = 0
SERVING = 1
DROPPED = 2
CollectionStats
CollectionStats
包含以下属性
属性 | 说明 |
---|---|
collection_name | 集合名称,str类型。 |
collection_path | 集合路径,str类型。 |
total_doc_count | 文档总数,long类型。 |
total_segment_count | 分段总个数,long类型。 |
total_index_file_count | 索引文件总个数,long类型。 |
total_index_file_size | 索引文件总大小,long类型。 |
segment_stats | 分段统计信息,List[CollectionStats.SegmentStats]类型。 |
CollectionStats.SegmentStats
包含以下属性
属性 | 说明 |
---|---|
segment_id | 段id,int类型。 |
state | 段状态,CollectionStats.SegmentState类型。 |
doc_count | 文档数,long类型。 |
index_file_count | 索引文件个数,long类型。 |
index_file_size | 索引文件大小,long类型。 |
min_doc_id | 当前分段的最小文档id,long类型。 |
max_doc_id | 当前分段的最大文档id,long类型。 |
min_primary_key | 当前分段的最小主键,long类型。 |
max_primary_key | 当前分段的最大主键,long类型。 |
min_timestamp | 当前分段的最小时间戳,long类型。 |
max_timestamp | 当前分段的最大时间戳,long类型。 |
min_lsn | 当前分段的最小日志序列号,long类型。 |
max_lsn | 当前分段的最大日志序列号,long类型。 |
segment_path | 段文件路径,str类型。 |
CollectionStats.SegmentState
定义如下
class SegmentState(IntEnum):
CREATED = 0
WRITING = 1
DUMPING = 2
COMPACTING = 3
PERSIST = 4
LsnContext
LsnContext
包含以下属性
属性 | 说明 |
---|---|
lsn | 序列号,long类型。 |
context | 上下文,str类型。 |
7. 其他示例
8. Python API Reference
2 - C++ SDK
ProximaBE的C++ SDK主要是针对用户上游C/C++模块的集成,其具备高吞吐和低负载的特点,功能上主要是包含集合管理、文档读写等能力,可以节省用户的编码成本。
这篇文章中,我们将介绍C++ SDK核心接口的用法以及代码示例,以协助用户更快接入。
1. 创建客户端
第一步,需要创建客户端,默认客户端采用grpc协议,且为同步调用。
#include <iostream>
#include "proxima_searcher_client.h"
using proxima::be;
// 默认类型客户端
auto client = ProximaSearchClient::Create();
第二步,创建完客户端之后,我们需要显示连接ProximaBE服务:
// 设置连接参数,注意这里需要填写grpc协议监听端口
ChannelOptions options("127.0.0.1:16000");
// 连接服务端
Status status = client->connect(options);
if (status.code != 0) {
std::cerr << "Connect server failed." << std::endl;
return status.code;
}
我们在连接过程中,除了简单的测试rpc连通性之外,还会与server校验版本信息,确保兼容性。
客户端所有接口,都会返回Status,用户需要检查status.code是否正常,其结构如下:
struct Status {
/// 错误码,0代表成功,其它非0代表调用错误
int code;
/// 错误原因, 默认为"Success",否则是错误描述
std::string reason;
}
代码中涉及到其它结构以及字段,可以参见ChannelOptions
2. 集合管理
我们提供了Collection的创建、删除、查询、统计等接口,供用户方便的管理集合。
2.1. 创建Collection
创建一个名为Plants的集合,其中正排列为价格"price"以及描述"description",索引列为向量列,存储4维float类型
/// 描述Collection的具体格式
CollectionConfig config;
config.collection_name = "Plants";
config.forward_columns = {"Price", "Description"};
config.index_columns = {IndexColumnParam("ImageVector", DataType::VECTOR_FP32, 8)}
/// 创建Collection
Status status = client->create_collection(config);
if (status.code != 0) {
std::cerr << "Create collection failed." << std::endl;
return status.code;
}
集合配置详细信息请参考: CollectionConfig
2.2. 查询Collection
创建完集合之后,我们可以使用查询接口查看其状态。
/// 获取CollectionInfo
CollectionInfo collection_info;
Status status = client->describe_collection("Plants", &collection_info);
if (status.code != 0) {
std::cerr << "Get collection info failed." << std::endl;
return status.code;
}
/// 打印CollectionInfo
std::cout << collection_info.collection_name << std::endl;
std::cout << collection_info.collection_status << std::endl;
std::cout << collection_info.uuid << std::endl;
......
除此之外,我们还可以将所有Collection信息一次性列出来
/// 获取所有的Collection信息
std::vector<CollectionInfo> collection_infos;
Status status = client->list_collections(&collection_infos);
if (status.code != 0) {
std::cerr << "List collection infos failed." << std::endl;
return status.code;
}
返回的集合信息详细字段请参考: CollectionInfo
2.3. 统计Collection
Collection经过一段时间的读写之后,我们可以通过统计接口观察其装载的文档数据。
/// 获取CollectionStats
CollectionStats collection_stats;
Status status = client->stats_collection("Plants", &collection_stats);
if (status.code != 0) {
std::cerr << "Get collection statistics failed." << std::endl;
return status.code;
}
/// 打印CollectionStats
std::cout << collection_stats.collection_name << std::endl;
std::cout << collection_stats.total_doc_count << std::endl;
std::cout << collection_stats.total_segment_cout << std::endl;
.....
集合统计详细字段信息请参考: CollectionStats
2.4. 删除Collection
Collection完成其历史使命后,我们可以彻底删除掉某个collection。
/// 删除集合
Status status = client->drop_collection("Plants");
if (status.code != 0) {
std::cerr << "Drop collection failed." << std::endl;
return status.code;
}
3. 文档管理
对于某一个集合而言,我们提供增加、更新、删除文档的接口,同时支持批量模式。
3.1. 插入文档
我们在之前已经创建完成的名为"Plants"的集合中,插入100条数据
/// 创建一个写入请求
auto write_request = WriteRequest::Create();
/// 设置集合以及文档数据格式
write_request->set_collection_name("Plants");
write_request->add_forward_columns({"Price", "Description"});
write_request->add_index_column("ImageVector", DataType::VECTOR_FP32, 8);
/// 批量填充100条文档数据
for (int i = 0; i < 100; i++) {
auto row = write_request->add_row();
row->set_primary_key(i);
/// 设置为插入操作
row->set_operation_type(OperationType::INSERT);
row->add_forward_value((float)i + 0.1f);
row->add_forward_value("iris with number " + std::to_string(i));
row->add_index_value({i, i, i, i, i, i, i, i});
}
/// 写入到服务端
Status status = client->write(*write_request);
if (status.code != 0) {
std::cerr << "Write records failed." << std::endl;
return status.code;
}
在上述参考代码中,有几点值得注意:
-
设置文档数据格式。 这里最早其实在创建Collection时候,我们填写过一次,这里需要再次设置的主要原因有两个。 第一个是由于我们未来会支持实时量化的能力,可能用户配置的类型与输入类型不一致,使用我们动态转换的能力。第二个则是我们可以基于这个信息做二次校验,防止插入数据格式错误。
-
批量模式。 理论上在一个WriteRequest中我们可以组合任意多的文档,但由于会增大单个网络请求包大小,一般还是建议用户根据实际情况进行限制。
3.2. 更新文档
更新过程基本与插入过程一致,仅改变文档的操作类型即可。
.....
/// 批量更新100条文档数据
for (int i = 0; i < 100; i++) {
auto row = write_request->add_row();
row->set_primary_key(i);
/// 设置为更新操作
row->set_operation_type(OperationType::UPDATE);
row->add_forward_value((float)i + 0.2f);
row->add_forward_value("iris with number " + std::to_string(i));
row->add_index_value({i, i, i, i, i, i, i, i});
}
......
NOTE: 值得注意的是,目前我们实际实现中采取的是标记删除的模式,更新=删除+新增,而删除占比过高会极大影响查询性能,这一点用户务必注意。
写入请求的详细信息可以参考: WriteRequest
3.3. 删除文档
删除过程依然可以复用上述的代码结构,如果批量请求中没有插入、更新请求,那么代码可以极大简化。
/// 创建一个写入请求
auto write_request = WriteRequest::Create();
/// 设置集合以及文档数据格式
write_request->set_collection_name("Plants");
/// 批量删除100条文档数据
for (int i = 0; i < 100; i++) {
auto row = write_request->add_row();
/// 设置为删除操作,仅需要填写primary key即可
row->set_primary_key(i);
row->set_operation_type(OperationType::DELETE);
}
/// 发送到服务端
Status status = client->write(*write_request);
if (status.code != 0) {
std::cerr << "Write records failed." << std::endl;
return status.code;
}
NOTE: 值得注意的是,由于我们内部采用图索引结构,删除目前采取标记删除方式,删除比例过高会带来连通性问题,影响召回和性能。我们一般不建议用户删除超过50%的文档,否则查询性能将会弱化很多。
4. 文档查询
最后我们希望能够在创建的"Plants"集合中查询这100条数据,相似度召回10条结果。
auto query_request = QueryRequest::Create();
auto query_response = QueryResponse::Create();
/// 填充请求参数
query_request->set_collection_name("Plants");
auto knn_param = query_request->add_knn_query_param();
knn_param->set_column_name("ImageVector");
knn_param->set_topk(10);
knn_param->set_features({0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8});
/// Knn查询
Status status = client->query(*query_request, query_response.get());
if (status.code != 0) {
std::cerr << "Query records failed." << std::endl;
return status.code;
}
/// 打印结果
for (size_t i = 0; i < query_response->result_count(); i++) {
auto result = query_response->result(i);
for (size_t j = 0; j < result->document_count(); j++){
auto doc = result->document(j);
/// 获取文档的primary key和相似度距离
std::cout << doc->primary_key() << std::endl;
std::cout << doc->score() << std::endl;
/// 按顺序取正排字段
float price;
std::string desc;
doc->get_forward_value("Price", &price);
doc->get_forward_value("Description", &desc);
std::cout << price << std::endl;
std::cout << desc << std::endl;
}
}
我们query同样也可以支持批量模式
const *vector_bytes;
size_t vector_size;
......
auto knn_param = query_request->add_knn_query_param();
knn_param->set_column_name("ImageVector");
knn_param->set_topk(10);
knn_param->set_features(vector_bytes, vector_size, 100);
knn_param->set_data_type(DataType::VECTOR_FP32);
knn_param->set_dimension(8);
上述代码中描述了设置一段连续的bytes作为查询向量,包含100个连续的查询向量,其中每个为8维float类型。
NOTE: 还有一点值得注意的是,最终的正排数据的获取,必须按照CollectionConfig定义的顺序逐一获取,顺序不对或者类型不对,均会导致获取到空结果
上述参考代码中查询请求和查询结果的详细信息请参考: QueryRequest
5. 错误码
错误码 | 错误原因 | 备注 |
---|---|---|
0~9999 | 服务端错误 | |
10000 | 初始化客户端失败 | |
10001 | RPC连接出错 | |
10002 | 客户端与服务端版本不匹配 | |
10003 | 客户端还未连接 | |
10004 | 请求校验失败 |
6. 接口&类型
ProximaSearchClient
/**
* ProximaSearchClient wrappers the operations used to call proxima search
* engine's service. Server may be running on another machines. It shields
* implementation of communication protocol and rpc details, and provide
* extremely high bench performance.
*
* Usage exp:
* auto client = ProximaSearchClient::Create();
* if (client != nullptr) {
* client->connect(ChannelOptions("127.0.0.1:16000"));
* ...
* client->create_collection();
* client->close();
* }
*
* Please read the examples/client_example.cc for more details.
*
* Note: the functions of this class are sync call.
*/
class ProximaSearchClient {
public:
/// @brief Create a client instance and return its shared ptr.
///
/// @param type Client type, only support "GrpcClient" now.
/// @return Shared ptr pointed to client impl.
///
/// @note If input type is wrong, it may return nullptr
static ProximaSearchClientPtr Create(const std::string &type);
//! Create a shared ptr of client with default type
static ProximaSearchClientPtr Create();
/// @brief Try to connect remote server and establish connection.
///
/// @param options Socket connection relative configs.
/// @return Status.code 0 means success, other means fail
///
/// @note This function will try to send a list collections command
/// to test if the server alive.
virtual Status connect(const ChannelOptions &options) = 0;
//! Close connection to remote server and cleanup self
virtual Status close() = 0;
/// @brief Create a collection with specific config.
///
/// @param config Collection config
/// @return Status.code 0 means success, other means fail
virtual Status create_collection(const CollectionConfig &config) = 0;
/// @brief Drop a collection with specific name.
///
/// @param collection_name Collection name
/// @return Status.code 0 means success, other means fail
virtual Status drop_collection(const std::string &collection_name) = 0;
/// @brief Show the detailed information of collection.
///
/// @param[in] collection_name Collection name
/// @param[out] collection_info Collection information
/// @return Status.code 0 means success, other means fail
virtual Status describe_collection(const std::string &collection_name,
CollectionInfo *collection_info) = 0;
/// @brief Get collection statics.
///
/// @param[in] collection_name Collection name
/// @param[out] stats Collection statistics struct
/// @return Status.code 0 means success, other means fail.
virtual Status stats_collection(const std::string &collection_name,
CollectionStats *stats) = 0;
/// @brief List all collections.
///
/// @param[out] collections Collection infomations
/// @return Status.code 0 means success, other means fail
virtual Status list_collections(std::vector<CollectionInfo> *collections) = 0;
/// @brief Insert/Update/Delete records.
///
/// @param request Write request
/// @return Status.code means success, other means fail
virtual Status write(const WriteRequest &request) = 0;
/// @brief Knn query similar results
///
/// @param[in] request Query request
/// @param[out] respnose Query response
/// @return Status.code means success, other means fail
virtual Status query(const QueryRequest &request,
QueryResponse *response) = 0;
/// @brief Get document by primary key
///
/// @param[in] request Get document request
/// @param[out] response Get document response
/// @return Status.code means success, other means fail
virtual Status get_document_by_key(const GetDocumentRequest &request,
GetDocumentResponse *response) = 0;
};
ChannelOptions
/**
* ChannelOptions represents the connection config.
*/
struct ChannelOptions {
/// Host name of proximabe server
/// For exapmle: "127.0.0.1:16000"
/// Required field
std::string host{};
/// Max rpc duration out over server
/// Optional field, default 1000
uint32_t timeout_ms{1000U};
/// Max retry times when rpc failed
/// Optional filed, default 3
uint32_t max_retry{3U};
/// Connection pool count
/// Optional filed, default 1
uint32_t connection_count{1};
ChannelOptions(const std::string &val) : host(val) {}
};
CollectionConfig
/**
* CollectionConfig describes the config options of collection.
* It includes description of index columns and forward columns.
* Index columns means that this column data is for knn searching.
* Forward columns means that this column data is just for display,
* which is not anticipating in search process.
*/
struct CollectionConfig {
/// Collection name, it should be unique
/// Required field
std::string collection_name{};
/// Collection will split into serveral segments
/// This param means max doc limits in one segment
/// Optional field, default 0, means no limit
uint32_t max_docs_per_segment{0U};
/// Forward column names
/// Optional field
std::vector<std::string> forward_columns{};
/// Index column infos
/// Required filed
std::vector<IndexColumnParam> index_columns{};
/// Database repository config
/// Optional field, default empty
DatabaseRepository database_repository{};
};
/**
* IndexColumnParam represents the index config of index column.
*/
struct IndexColumnParam {
/// Column name
/// Required field
std::string column_name{};
/// Column index type
/// Optional field, default IndexType::PROXIMA_GRAPH_INDEX
IndexType index_type{IndexType::PROXIMA_GRAPH_INDEX};
/// Stored data type
/// Optional filed, default DataType::VECTOR_FP32
DataType data_type{DataType::VECTOR_FP32};
/// Stored data dimension
/// Optional filed, default 0
uint32_t dimension{0U};
/// Extra params for column index
/// Optional field
/// For example:
/// {"ef_construction": "400", "ef_search": "300"}
std::vector<KVPair> extra_params{};
IndexColumnParam() = default;
IndexColumnParam(const std::string &val1, DataType val2, uint32_t val3)
: column_name(val1), data_type(val2), dimension(val3) {}
};
CollectionInfo
/**
* CollectionInfo describes the detailed information of collection,
* which is ProximaSE server returned.
*/
struct CollectionInfo {
enum class CollectionStatus : uint32_t {
INITIALIZED = 0,
SERVING = 1,
DRPPED = 2
};
//! Collection name
std::string collection_name{};
//! Collection status
CollectionStatus collection_status{CollectionStatus::INITIALIZED};
//! Unique uuid to a collection
std::string collection_uuid{};
//! Latest record's log sequence number
uint64_t latest_lsn{0U};
//! Latest record's lsn context
std::string latest_lsn_context{};
//! Server magic number, generally is server started timestamp
uint64_t magic_number{0U};
//! Collection's config max doc number per segment
uint32_t max_docs_per_segment{0U};
//! Collection's forward column names
std::vector<std::string> forward_columns{};
//! Collection's index column params
std::vector<IndexColumnParam> index_columns{};
//! Collection's database repository information
DatabaseRepository database_repository{};
};
CollectionStats
/**
* CollectionStats describes the detailed stastistics of collection
*/
struct CollectionStats {
/**
* Segment state
*/
enum class SegmentState : uint32_t {
CREATED = 0,
WRITING = 1,
DUMPING = 2,
COMPACTING = 3,
PERSIST = 4
};
/*
* SegmentStats describes the detailed stastistics of segment
*/
struct SegmentStats {
//! Segment unique id
uint64_t segment_id{0U};
//! Segment state
SegmentState segment_state{SegmentState::CREATED};
//! Document count in this segment
uint64_t doc_count{0U};
//! Index file count of this segment
uint64_t index_file_count{0U};
//! Totaol index file size
uint64_t index_file_size{0U};
//! Min document id
uint64_t min_doc_id{0U};
//! Max document id
uint64_t max_doc_id{0U};
//! Min primary key value of the segment
uint64_t min_primary_key{0U};
//! Min primary key value of the segment
uint64_t max_primary_key{0U};
//! Earliest record timestamp
uint64_t min_timestamp{0U};
//! Last record timestamp
uint64_t max_timestamp{0U};
//! Minimal log sequence number
uint64_t min_lsn{0U};
//! Maximum log sequence number
uint64_t max_lsn{0U};
};
//! Collection name
std::string collection_name{};
//! Total document count of this collection
uint64_t total_doc_count{0U};
//! Total segment count of this collectoin
uint64_t total_segment_count{0U};
//! Total index file count
uint64_t total_index_file_count{0U};
//! Total index file size
uint64_t total_index_file_size{0U};
//! Detailed segment stastistics
std::vector<SegmentStats> segment_stats{};
};
WriteRequest
/**
* WriteRequest shows how to wrapper write request data fields.
*
* Usage exp:
* WriteRequestPtr request = WriteRequest::Create();
* request->set_collection_name("test_collection");
* request->set_row_meta({"test_column"}, {});
* auto row = request->add_row();
* row->set_primary_key = 123;
* row->set_operation_type(OperationType::OP_INSERT);
* row->add_index_value({0.1, 0.2, 0.3});
* ...
* client->write(*request);
*/
class WriteRequest {
public:
/**
* A row describes the format of one record
*/
class Row {
public:
//! Set primary key, required
virtual void set_primary_key(uint64_t val) = 0;
//! Set operation type, optional, default DataType::INSERT
virtual void set_operation_type(OperationType op_type) = 0;
//! Set lsn, optional, default 0
virtual void set_lsn(uint64_t lsn) = 0;
//! Set lsn context, optional, default ""
virtual void set_lsn_context(const std::string &lsn_context) = 0;
/// @brief Add forward value with string type
///
/// @note Add forward value sort must match configured
/// forward columns in CollectionConfig
virtual void add_forward_value(const std::string &val) = 0;
//! Add forward value with bool type
virtual void add_forward_value(bool val) = 0;
//! Add forward value with int32 type
virtual void add_forward_value(int32_t val) = 0;
//! Add forward value with int64 type
virtual void add_forward_value(int64_t val) = 0;
//! Add forward value with uint32 type
virtual void add_forward_value(uint32_t val) = 0;
//! Add forward value with uint64 type
virtual void add_forward_value(uint64_t val) = 0;
//! Add forward value with float type
virtual void add_forward_value(float val) = 0;
//! Add forward value with double type
virtual void add_forward_value(double val) = 0;
/// @brief Add index value, vector bytes type
///
/// @note Add index value sort must match configured
/// index columns in CollectionConfig
virtual void add_index_value(const void *val, size_t val_len) = 0;
//! Add index value, vector array type
virtual void add_index_value(const std::vector<float> &val) = 0;
/// Add index value by json format
/// Two json format:
/// "[0.1, 0.2, 0.3, 0.4]"
/// "[[0.1, 0.2, 0.3, 0.4], [0.5, 0.6, 0.7, 0.8]]"
virtual void add_index_value_by_json(const std::string &json_val) = 0;
};
using RowPtr = std::shared_ptr<Row>;
public:
//! Constructor
static WriteRequestPtr Create();
//! Set collection name, required, must be unique
virtual void set_collection_name(const std::string &val) = 0;
/// @brief Add forward column in row meta
/// @note Forward column names' sort must match configured
/// forward columns in CollectionConfig
virtual void add_forward_column(const std::string &column_name) = 0;
/// @brief Add forward columns in row meta
/// @note Forward column names' sort must match configured
/// forward columns in CollectionConfig
virtual void add_forward_columns(
const std::vector<std::string> &column_names) = 0;
/// @brief Add index column in row meta
///
/// @param column_name Column name
/// @param data_type Send data type
/// @param dimension Send data dimension
///
/// @note Index column names' sort must match configured
/// index columns in CollectionConfig
virtual void add_index_column(const std::string &column_name,
DataType data_type, uint32_t dimension) = 0;
//! Add row data, required, can't send empty request
virtual WriteRequest::RowPtr add_row() = 0;
//! Set request id for tracelog, optional
virtual void set_request_id(const std::string &request_id) = 0;
//! Set magic number for validation, optional
virtual void set_magic_number(uint64_t magic_number) = 0;
};
QueryRequest
/**
* QueryRequest shows how to wrapper query data fields.
*
* Usage exp:
* QueryRequestPtr request = QueryRequest::Create();
* request->set_collection_name("test_colletion");
* auto knn_param = request->add_knn_query_param();
* knn_param->set_column_name("test_column");
* knn_param->set_features({0.1, 0.2, 0.3, 0.4});
* knn_param->set_batch_count(1);
* knn_param->set_dimension(4);
* knn_param->set_data_type(DT_VECTOR_FP32);
* ...
*
*/
class QueryRequest {
public:
/**
* KnnQueryParam describes the options of knn query
*/
class KnnQueryParam {
public:
//! Set column name, required
virtual void set_column_name(const std::string &val) = 0;
//! Set topk, required
virtual void set_topk(uint32_t val) = 0;
/// Set query vector with bytes format by single
/// Required set
virtual void set_features(const void *val, size_t val_len) = 0;
//! Set features with vector array format by single
virtual void set_features(const std::vector<float> &val) = 0;
//! Set query vector with bytes format by batch
virtual void set_features(const void *val, size_t val_len,
uint32_t batch) = 0;
/// Set features by json format
/// Two json format:
/// "[0.1, 0.2, 0.3, 0.4]"
/// "[[0.1, 0.2, 0.3, 0.4], [0.5, 0.6, 0.7, 0.8]]"
virtual void set_features_by_json(const std::string &json_val) = 0;
//! Set features by json format and by batch
virtual void set_features_by_json(const std::string &json_val,
uint32_t batch) = 0;
//! Set vector data dimension, required
virtual void set_dimension(uint32_t val) = 0;
//! Set vector data type, required
virtual void set_data_type(DataType val) = 0;
//! Set search radius, optional, default 0.0f not open
virtual void set_radius(float val) = 0;
//! Set if use linear search, optional, default false
virtual void set_linear(bool val) = 0;
//! Add extra params, like ef_search ..etc, optional
virtual void add_extra_param(const std::string &key,
const std::string &val) = 0;
};
using KnnQueryParamPtr = std::shared_ptr<KnnQueryParam>;
public:
//! Constructor
static QueryRequestPtr Create();
//! Set collection name, required
virtual void set_collection_name(const std::string &val) = 0;
//! Set knn query param, required
virtual QueryRequest::KnnQueryParamPtr add_knn_query_param() = 0;
//! Set debug mode, optional, default false
virtual void set_debug_mode(bool val) = 0;
};
QueryResponse
/**
* QueryResponse shows the format of query response.
*/
class QueryResponse {
public:
/**
* Result represents a knn query's result
*/
class Result {
public:
//! Return document count
virtual size_t document_count() const = 0;
//! Return document pointer of specific pos
virtual DocumentPtr document(int index) const = 0;
};
public:
//! Constructor
static QueryResponsePtr Create();
//! Return debug info
virtual const std::string &debug_info() const = 0;
//! Return query latency, microseconds
virtual uint64_t latency_us() const = 0;
//! Return batch result count
virtual size_t result_count() const = 0;
//! Return result pointer of specific batch pos
virtual QueryResponse::ResultPtr result(int index) const = 0;
};
/**
* Document shows the format of knn query response
*/
class Document {
public:
//! Return document primary key
virtual uint64_t primary_key() const = 0;
//! Return calculated knn distance score
virtual float score() const = 0;
//! Return forward values count
virtual size_t forward_count() const = 0;
//! Get forward names
virtual void get_forward_names(
std::vector<std::string> *forward_names) const = 0;
//! Get forward value with string type
virtual void get_forward_value(const std::string &key,
std::string *val) const = 0;
//! Get forward value with bool type
virtual void get_forward_value(const std::string &key, bool *val) const = 0;
//! Get forward value with int32 type
virtual void get_forward_value(const std::string &key,
int32_t *val) const = 0;
//! Get forward value with int64 type
virtual void get_forward_value(const std::string &key,
int64_t *val) const = 0;
//! Get forward value with uint32 type
virtual void get_forward_value(const std::string &key,
uint32_t *val) const = 0;
//! Get forward value with uint64 type
virtual void get_forward_value(const std::string &key,
uint64_t *val) const = 0;
//! Get forward value with float type
virtual void get_forward_value(const std::string &key, float *val) const = 0;
//! Get forward value with double type
virtual void get_forward_value(const std::string &key, double *val) const = 0;
};
3 - Java SDK
本文主要介绍用户如何使用 Java SDK,来进行集合管理、文档的增删改查等功能。
1. 前提条件
使用 ProximaBE 的 Java SDK,必须满足以下两点:
- JDK 1.8 或者以上版本
- 使用 Apache Maven
2. 安装 Java SDK
可以通过Apache Maven二方库依赖的方式,将 SDK 下载到自己的项目中。
<dependency>
<groupId>com.alibaba.proxima</groupId>
<artifactId>proxima-be-java-sdk</artifactId>
<version>0.1.2-SNAPSHOT</version>
</dependency>
3. 客户端创建
ProximaSearchClient 是ProximaBE 对外的所有接口的代理层,用户通过传入连接参数,创建该客户端对象,就可以对 ProximaBE 中的集合进行相关的操作。
3.1. 初始化连接参数
构建类:ConnectParam.Builder
首先通过调用 ConnectParam 的 newBuilder 接口,创建出 ConnectParam 的 Builder 对象,然后依次通过Builder对象设置 ProximaBE 的 host 地址,以及 grpc 端口等信息,最终调用 Builder的 build 接口,即可构建出 ConnectParam 对象。
Builder 参数说明:
参数 | 说明 |
---|---|
host | ProximaBE对应的服务地址,String类型默认为 localhost |
port | ProximaBE对应的GRPC服务端口,int类型,默认16000 |
IdleTimeout | GRPC链接空闲的超时时间,long类型,默认12小时 |
3.2. 创建客户端对象
接口:ProximaGrpcSearchClient(ConnectParam connectParam)
通过传入的 connectParam 对象创建 ProximaBE 客户端,目前支持 Grpc 协议,创建成功后返回 ProximaSearchClient 对象,目前 Client 中的接口均为同步接口。
参数说明:
- ConnectParam:表示连接 ProximaBE 所需要的相关连接参数信息
3.3. 示例
创建 ProximaSearchClient 对象
import com.alibaba.proxima.se.client.*;
// init connect params
ConnectParam connectParam = ConnectParam.newBuilder()
.withHost("127.0.0.1")
.withPort(16000)
.build();
// create client
ProximaSearchClient client = new ProximaGrpcSearchClient(connectParam);
4. 集合管理
集合管理主要包括集合的创建、集合的查询和集合的删除等操作。
4.1. 创建集合
4.1.1 创建 CollectionConfig
构造类:CollectionConfig.Builder
首先通过调用 CollectionConfig 的 newBuilder 接口,创建出 CollectionConfig 的 Builder 对象,然后通过 Builder 对象设置集合名称、索引列信息、正排列信息等,最终调用 Builder 的 build 接口,即可构建出 CollectionConfig 对象。
Builder 参数说明:
参数 | 说明 |
---|---|
collectionName | 集合的名称,String类型 |
indexColumnParams | 索引列参数列表,List |
forwardColumnNames | 正排列的名称列表,List |
maxDocsPerSegment | 分片最大文档数,long类型,默认值为0,表示不限制单片文档数 |
databaseRepository | 数据库源相关配置,如果是数据库旁路集合,需要配置该选项,目前只支持 mysql 数据库 |
IndexColumnParam 参数:
参数 | 说明 |
---|---|
columnName | 索引列名称,String 类型 |
indexType | 索引类型,IndexType 类型,目前支持 PROXIMA_GRAPH_INDEX 类型索引 |
dataType | 索引列数据类型,DataType 类型 |
dimension | 索引的维度,int 类型 |
extraParams | 其它的参数,Map类型 |
4.1.2 调用创建接口
接口: Status createCollection(CollectionConfig collectionConfig)
根据参数 CollectionConfig 对象创建集合,返回值为 Status 对象,表示集合创建成功与否,如果传入的 CollectionConfig 对象非法,会抛出 ProximaBEException 异常。
参数说明:
- collectionConfig:其中包含了集合的基础配置信息,主要有集合名称、索引列信息、正排列名称列表等。
返回值:
- Status:表示创建成功与否,其中包含错误码和错误描述
4.1.3 示例
示例 1:创建一个带有两个正排列,以及单个向量索引列的集合
public boolean createCollection(ProximaSearchClient client) {
String collectionName = "collection1";
int dimension = 8;
// create collection builder
CollectionConfig config = CollectionConfig.newBuilder()
.withCollectionName(collectionName) // set collection name
.withForwardColumnNames(Arrays.asList("forward1", "forward2")) // set forward column names
.addIndexColumnParam("index1", DataType.VECTOR_FP32, dimension)// add one index column param
.build(); // build the CollectionConfig
// call create collection interface
try {
Status status = client.createCollection(config);
if (status.ok()) {
System.out.println("============== Create collection success. ================");
return true;
} else {
System.out.println("Create collection failed." + status.toString());
return false;
}
} catch (ProximaBEException e) {
e.printStackTrace();
return false;
}
}
示例 2:创建一个带有两个正排列、单个向量索引列、以及作为Mysql 数据旁路的集合
public boolean createCollectionWithRepo(ProximaSearchClient client) {
String collectionName = "collection2";
int dimension = 8;
// create database repository
DatabaseRepository repo = DatabaseRepository.newBuilder()
.withConnectionUri("mysql://host.com:8080/mysql_database") // set connection uri
.withTableName("mysql_table1") // set table name
.withRepositoryName("mysql_repo") // set repository name
.withUser("root") // set user name
.withPassword("root") // set password
.build();
// create collection builder
CollectionConfig config = CollectionConfig.newBuilder()
.withCollectionName(collectionName) // set collection name
.withForwardColumnNames(Arrays.asList("forward1", "forward2")) // set forward column name list
.addIndexColumnParam("index1", DataType.VECTOR_FP32, dimension)// add one index column param
.withDatabaseRepository(repo) // set database repoistory
.build();
// call create collection interface
try {
Status status = client.createCollection(config);
if (status.ok()) {
System.out.println("============== Create collection success. ================");
return true;
} else {
System.out.println("Create collection failed." + status.toString());
return false;
}
} catch (ProximaBEException e) {
e.printStackTrace();
return false;
}
}
4.2. 查询集合配置信息
接口: DescribeCollectionResponse describeCollection(String collectionName)
根据传入的集合名称,获取当前集合对应的相关配置信息。
参数说明:
- collectionName:集合名称
返回值:
- DescribeCollectionResponse:其中包含 Status 以及 CollectionInfo 两部分,Status 描述当前请求成功与否,CollectionInfo 描述集合的配置信息
示例:
查询 collection 的配置信息
public boolean describeCollection(ProximaSearchClient client) {
String collectionName = "collection1";
// describe collection
DescribeCollectionResponse descResponse = client.describeCollection(collectionName);
if (descResponse.ok()) {
System.out.println("================ Describe collection success. ===================");
CollectionInfo info = descResponse.getCollectionInfo();
CollectionConfig collectionConfig = info.getCollectionConfig();
System.out.println("CollectionName: " + collectionConfig.getCollectionName());
System.out.println("CollectionStatus: " + info.getCollectionStatus());
System.out.println("Uuid: " + info.getUuid());
System.out.println("Forward columns: " + collectionConfig.getForwardColumnNames());
List<IndexColumnParam> indexColumnParamList = collectionConfig.getIndexColumnParams();
for (int i = 0; i < indexColumnParamList.size(); ++i) {
IndexColumnParam indexParam = indexColumnParamList.get(i);
System.out.println("IndexColumn: " + indexParam.getColumnName());
System.out.println("IndexType: " + indexParam.getDataType());
System.out.println("DataType: " + indexParam.getDataType());
System.out.println("Dimension: " + indexParam.getDimension());
}
return true;
} else {
System.out.println("Describe collection failed " + descResponse.toString());
return false;
}
}
4.3. 查询集合统计信息
接口: StatsCollectionResponse statsCollection(String collectionName)
根据传入的集合名称,获取当前集合对应的相关统计信息。
参数说明:
- collectionName:集合名称
返回值:
- StatsCollectionResponse:其中包含 Status 以及 CollectionStats 两部分,Status 描述当前请求成功与否,CollectionStats 描述集合的相关统计信息,包含的信息如下:
字段名称 | 说明 |
---|---|
collectionPath | collection 的索引路径 |
totalDocCount | 总的文档数量 |
totalSegmentCount | 总的segment数量 |
totalIndexFileCount | 总的索引文件数量 |
totalIndexFileSize | 总的索引文件大小 |
segmentStatsList | 每个 segment 相应的统计信息,包括 segment 的总文档数量、索 引文件数量和大小,以及最大/小 doc id等 |
示例 :
查询指定集合的统计信息
public boolean statsCollection(ProximaSearchClient client) {
String collectionName = "collection1";
// call stats collection interface
StatsCollectionResponse statsResponse = client.statsCollection(collectionName);
if (statsResponse.ok()) {
System.out.println("==================== Stats collection success. ======================");
CollectionStats stats = statsResponse.getCollectionStats();
System.out.println("CollectionName: " + stats.getCollectionName());
System.out.println("TotalDocCount: " + stats.getTotalDocCount());
System.out.println("TotalSegmentCount: " + stats.getTotalSegmentCount());
for (int i = 0; i < stats.getSegmentStatsCount(); ++i) {
System.out.println("Segment: " + i);
System.out.println("SegmentDocCount: " + stats.getSegmentStats(i).getDocDount());
System.out.println("SegmentIndexFileCount: " + stats.getSegmentStats(i).getIndexFileCount());
System.out.println("SegmentMaxDocId: " + stats.getSegmentStats(i).getMaxDocId());
}
return true;
} else {
System.out.println("Stats collection failed " + statsResponse.getStatus().toString());
return false;
}
}
4.4. 删除集合
接口: Status dropCollection(String collectionName)
删除指定集合,集合名由参数 collectionName 指定
参数说明:
- collectionName:删除的集合名称
返回值:
- Status:表示删除成功与否,其中包含错误码和错误描述
示例 :
删除指定集合
public boolean dropCollection(ProximaSearchClient client) {
String collectionName = "collection1";
// call drop collection interface
Status status = client.dropCollection(collectionName);
if (status.ok()) {
System.out.println("==================== Dorp collection success. ========================");
return true;
} else {
System.out.println("Drop collection failed " + status.toString());
return false;
}
}
4.5. 获取集合列表
接口: ListCollectionsResponse listCollections(ListCondition listCondition)
根据传入的 ListCondition 条件获取满足条件的集合列表
参数说明:
- listCondition:集合需要满足的条件,目前只包含了一个 Repository 名称字段,仅用在Mysql 同步数据时,如果该字段为空或者 listCondition 为空时,返回所有的集合
返回值:
- ListCollectionsResponse:包含 Status 和 CollectionInfo List 两部分,前者描述请求是否成功,后者描述所有集合的配置信息。
示例 :
获取 repository name 为 mysql_repo 的所有集合
public boolean listCollections(ProximaSearchClient client) {
// build list condition object
ListCondition listCondition = ListCondition.newBuilder()
.withRepositoryName("mysql_repo") // set repository name
.build();
// call list collections interface
ListCollectionsResponse listResponse = client.listCollections(listCondition);
if (listResponse.ok()) {
System.out.println("List collections success.");
for (int i = 0; i < listResponse.getCollectionCount(); ++i) {
System.out.println("Collection " + i);
CollectionInfo info = listResponse.getCollection(i);
CollectionConfig collectionConfig = info.getCollectionConfig();
System.out.println("CollectionName: " + collectionConfig.getCollectionName());
System.out.println("CollectionStatus: " + info.getCollectionStatus());
System.out.println("Uuid: " + info.getUuid());
System.out.println("Forward columns: " + collectionConfig.getForwardColumnNames());
List<IndexColumnParam> indexColumnParamList = collectionConfig.getIndexColumnParams();
for (int j = 0; j < indexColumnParamList.size(); ++j) {
IndexColumnParam indexParam = indexColumnParamList.get(j);
System.out.println("IndexColumn: " + indexParam.getColumnName());
System.out.println("IndexType: " + indexParam.getDataType());
System.out.println("DataType: " + indexParam.getDataType());
System.out.println("Dimension: " + indexParam.getDimension());
}
}
return true;
} else {
System.out.println("List collections failed " + listResponse.toString());
return false;
}
}
5. 文档管理
文档管理主要包括文档的插入、更新和删除操作,ProximaBE 中将文档的这三种操作,整合为一个通用的 Write 接口,通过一个 WriteRequest 结构来描述相关的操作,WriteRequest 中既可以描述单条记录的操作,也可以描述批量记录的操作。
5.1. 创建 WriteRequest
构造类:WriteRequest.Builder
首先通过 WriteRequest 的 newBuilder() 接口创建出 WriteRequest 的 Builder 对象,然后通过 Builder 对象设置相关参数,包括集合名称、正排列和索引列,以及 Rows等信息,最终调用 Builder 的 build 接口创建出 WriteRequest 对象。
参数说明:
参数 | 说明 |
---|---|
collectionName | 集合名称,String类型 |
forwardColumnList | 正排列的名称列表,List类型,插入和更新时必须要设置,删除时不需要设置 |
indexColumnMetaList | 索引列的 Meta 列表,插入和更新时必须要设置,删除时不需要设置 |
rows | 请求中包含的文档操作列表,List类型,每一个 row 表示一个文档操作,具体内容见 Rows 参数说明 |
requestId | 请求的 id,String类型,默认为空 |
magicNumber | 请求中的魔数,long类型,仅在通过 Mysql 作为数据源时需要设置 |
Row 参数说明
参数 | 说明 |
---|---|
primaryKey | row的主键,long类型 |
operationType | row的操作类型,候选值为 INSERT、UPDATE、DELETE三种 |
indexValues | 对应索引列的值列表,List类型,operationType为DELETE操作时,不需要指定,支持三种格式:
|
forwardValues | 对应正排列的值列表,List类型,operationType为DELETE时,不需要指定 |
lsnContext | mysql 的 lsn 信息,仅当用 mysql 做数据同步时需要 |
5.2. 执行写入
接口: Status write(WriteRequest request)
向 ProximaBE 中写入文档操作请求,执行完成后返回 Status,表示执行成功与否,如果传入的 WriteRequest 请求非法,会抛出 ProximaBEException 异常。
参数说明:
- request:包含某个集合的插入、更新和删除等文档操作
返回值:
- Status:表示写入请求的成功与否
5.3. 示例
示例1:向集合 collection1 中分别插入和更新一条记录
public boolean write1(ProximaSearchClient client) {
String collectionName = "collection1";
float[] vectors1 = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f};
float[] vectors2 = {1.5f, 2.5f, 3.5f, 4.5f, 5.5f, 6.5f, 7.5f, 8.5f};
int dimension = 8;
long primaryKey = 123456;
int forward1Value = 123;
float forward2Value = 100.123f;
// build insert row
WriteRequest.Row insertRow = WriteRequest.Row.newBuilder()
.withPrimaryKey(primaryKey) // set primary key
.withOperationType(WriteRequest.OperationType.INSERT) // set operation type
.addIndexValue(vectors1) // add one index value
.addForwardValue(forward1Value) // add one forard value
.addForwardValue(forward2Value) // add one forward value
.build();
// build update row
WriteRequest.Row updateRow = WriteRequest.Row.newBuilder()
.withPrimaryKey(primaryKey) // set primary key
.withOperationType(WriteRequest.OperationType.UPDATE) // set operation type
.addIndexValue(vectors2) // add index value
.addForwardValue(forward1Value) // add forward value
.addForwardValue(forward2Value) // add forward value
.build();
// build delete row
long deleteKey = 10000;
WriteRequest.Row deleteRow = WriteRequest.Row.newBuilder()
.withPrimaryKey(deleteKey) // set primary key
.withOperationType(WriteRequest.OperationType.DELETE) // set operation type
.build();
// build write request
WriteRequest writeRequest = WriteRequest.newBuilder()
.withCollectionName(collectionName) // set collection name
.withForwardColumnList(Arrays.asList("forward1", "forward2")) // set forward column list
.addIndexColumnMeta("index1", DataType.VECTOR_FP32, dimension) // add one index column meta, otherwise call withIndexColumnMetaList
.addRow(insertRow) // add insert row
.addRow(updateRow) // add update row
.addRow(deleteRow) // add delete row
.build();
try {
// call write interface
Status status = client.write(writeRequest);
if (status.ok()) {
System.out.println("============== Write success. ===============");
return true;
} else {
System.out.println("Write failed " + status.toString());
return false;
}
} catch (ProximaBEException e) {
e.printStackTrace();
return false;
}*/
}
示例2:向集合 collection1 中删除一条记录
public boolean write2(ProximaSearchClient client) {
String collectionName = "collection1";
// build delete row
long deleteKey = 123456;
WriteRequest.Row deleteRow = WriteRequest.Row.newBuilder()
.withPrimaryKey(deleteKey) // set primary key
.withOperationType(WriteRequest.OperationType.DELETE) // set operation type
.build();
// build write request
WriteRequest writeRequest = WriteRequest.newBuilder()
.withCollectionName(collectionName) // set collection name
.addRow(deleteRow) // add delete row
.build();
try {
// call write interface
Status status = client.write(writeRequest);
if (status.ok()) {
System.out.println("============== Write success. ===============");
return true;
} else {
System.out.println("Write failed " + status.toString());
return false;
}
} catch (ProximaBEException e) {
e.printStackTrace();
return false;
}*/
}
6. 文档查询
文档查询目前主要包括两种类型,一种是根据向量来进行 knn 的查询,另一种是直接根据文档的主键来查询相应的文档。
6.1. 向量查询
6.1.1 创建 QueryRequest
构造类:QueryRequest.Builder
通过 QueryRequest 的 newBuilder 接口创建出 QueryRequest 的 Builder 对象,然后通过 Builder 对象设置相关查询参数,主要包括集合名称和 KnnQueryParam等参数,最终调用 Builder 的 build 接口构建出 QueryRequest 对象。
参数说明:
参数 | 说明 |
---|---|
collectionName | 要查询的集合名称,String类型 |
knnQueryParam | knn 查询的参数,KnnQueryParam类型,具体内容见下表 |
debugMode | 是否开启调试模式,boolean类型,默认为false |
KnnQueryParam 参数
参数 | 说明 |
---|---|
columnName | 要查询的索引列名,String类型 |
topk | 查询的结果数量,int类型,默认为100 |
features | 查询的特征,可以是单个或者多个向量,支持三种类型:
|
dataType | 查询向量的数据类型,向量列表类型的特征支持自动推导,其它类型的必须设置 |
dimension | 查询向量的维度,向量列表类型的特征支持自动推导,其它类型的必须设置 |
batchCount | 查询的batch数量,向量列表类型的特征支持自动推导,其它类型的必须设置 |
radius | 过滤结果的分数阈值,仅当分数小于该阈值的结果会返回,float类型,默认值为0,表示不过滤 |
isLinear | 是否使用暴力检索,boolean类型,默认false |
6.1.2 执行查询
接口: QueryResponse query(QueryRequest request)
通过调用上述接口,向 ProximaBE 发起查询请求,返回 QueryResponse,当传入的 QueryRequest 非法时,会抛出 ProximaBEException 异常。
参数说明:
- request:表示查询请求,包含查询的集合以及查询的向量等信息
返回值:
- QueryResponse:表示查询的返回结果,包含查询的状态信息,以及查询的文档结果。
6.1.3. 示例
根据某个向量查询最相似的文档
public boolean query(ProximaSearchClient client) {
String collectionName = "collection1";
float[] features = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f};
// when batch querying, features can be following:
// float[][] features = {
// {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f},
// {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f}
// };
// build query request
QueryRequest queryRequest = QueryRequest.newBuilder()
.withCollectionName(collectionName) // set collection name
.withKnnQueryParam( // set knn query param
QueryRequest.KnnQueryParam.newBuilder() // new KnnQueryParam builder
.withColumnName("index1") // set index column name
.withTopk(10) // set topk
.withFeatures(features) // set query features
.build()) // build knnQueryParam object
.build(); // build query request
QueryResponse queryResponse = null;
try {
// call query interface
queryResponse = client.query(queryRequest);
} catch (ProximaBEException e) {
e.printStackTrace();
return false;
}
if (queryResponse.ok()) {
System.out.println("================ Query success =====================");
for (int i = 0; i < queryResponse.getQueryResultCount(); ++i) {
QueryResult queryResult = queryResponse.getQueryResult(i);
for (int d = 0; d < queryResult.getDocumentCount(); ++d) {
Document document = queryResult.getDocument(d);
System.out.println("Doc key: " + document.getPrimaryKey());
System.out.println("Doc score: " + document.getScore());
Set<String> forwardKeys = document.getForwardKeySet();
for (String forwardKey : forwardKeys) {
System.out.println("Doc forward: " + forwardKey + " -> " +
document.getForwardValue(forwardKey).getStringValue());
}
}
}
return true;
} else {
System.out.println("Query failed: " + queryResponse.getStatus().toString());
return false;
}
}
6.2. 主键查询
6.2.1 创建 GetDocumentRequest
构造类:GetDocumentRequest.Builder
通过 GetDocumentRequest 的 newBuilder 接口,创建出 GetDocumentRequest 的 Builder 对象,然后通过 Builder 对象设置相关查询参数,主要包括集合名称和 主键等参数,最终调用 Builder 的 build 接口构建出 GetDocumentRequest 对象。
Builder 参数说明:
参数 | 说明 |
---|---|
collectionName | 要查询的集合名称,String类型 |
primaryKey | 要查询的文档的主键,long类型 |
debugMode | 是否开启调试模式, boolean类型,默认为false |
6.2.2 执行查询
接口: GetDocumentResponse getDocumentByKey(GetDocumentRequest request)
通过调用上述接口,向 ProximaBE 发起查询请求,返回 GetDocumentResponse 对象,当传入的 GetDocumentRequest 非法时,会抛出 ProximaBEException 异常。
参数说明:
- request:表示查询指定文档请求
返回值:
- GetDocumentResponse:表示查询的返回结果,包含查询的状态信息,以及查询文档的结果。
6.2.3 示例
public boolean getDocument(ProximaSearchClient client) {
String collectionName = "collection1";
// build get document request
GetDocumentRequest getRequest = GetDocumentRequest.newBuilder()
.withCollectionName(collectionName) // set collection name
.withPrimaryKey(123456) // set primary key
.withDebugMode(true) // set debug mode, defalut false
.build(); // build GetDocumentRequest object
GetDocumentResponse getResponse = null;
try {
// call get document by key interface
getResponse = client.getDocumentByKey(getRequest);
} catch (ProximaBEException e) {
e.printStackTrace();
return false;
}
if (getResponse.ok()) {
System.out.println("======================== Get Document success ======================== ");
Document document = getResponse.getDocument();
System.out.println("PrimaryKey: " + document.getPrimaryKey());
System.out.println("Score: " + document.getScore());
Set<String> forwardKeys = document.getForwardKeySet();
for (String forwardKey : forwardKeys) {
System.out.println("Doc forward: " + forwardKey + " -> " +
document.getForwardValue(forwardKey).getStringValue());
}
System.out.println("DebugInfo: " + getResponse.getDebugInfo());
return true;
} else {
System.out.println("Get document failed " + getResponse.getStatus().toString());
return false;
}
}
4 - Golang SDK
用户可以使用Golang SDK进行集合管理、文档的增删该查等功能
1. BE客户端创建
ProximaSearchClient 是BE的客户端接口对象,用户通过该实例对象与BE进行交互,完成的管控功能
1.1. 创建客户端
NewProximaSearchClient(ConnectionProtocol, *Address) (ProximaSearchClient, error)
创建BE客户端,创建成功后返回ProximaSearchClient对象, 否则返回error。
参数说明:
- ConnectionProtocol: 与BE交互的协议类型,目前支持GRPC、HTTP两种协议,其中GRPC在性能以及资源占用上有明显的优势。
- *Address: 该参数指定BE的网络连接信息,主要包含BE的域名,以及端口号,详细定义如下:
// Address reference to entrypoint of ProximaBE
type Address struct {
// Host IP address or host name
Host string `json:"host:omitempty"`
// Port
Port uint32 `json:"port"`
}
返回值:
- ProximaSearchClient: BE客户端对象
- error: 执行错误时返回非nil
特殊说明:
- SDK中已封装了与BE通信的协议类型,如想进一步了解协议内容,请参考Restful API章节
示例: 创建BE客户端
package main
import (
"log"
"proxima-be-sdk-go/proxima/se/sdk"
)
func main() {
// Create client of BE with GRPC protocol and connect to localhost:16000
client, err := sdk.NewProximaSearchClient(sdk.GrpcProtocol, &sdk.Address{
Host: "localhost",
Port: 16000,
})
if err != nil {
log.Fatal("Can't create ProximaClient instance.", err)
}
}
2. 集合管理
2.1. 集合创建
CreateCollection(config *CollectionConfig) error
根据参数创建集合,创建成功后返回nil, 否则返回error。
参数说明:
- config: CollectionConfig中指定了集合的配置信息,包含不仅限于集合名、分片配置、正排列名、索引列信息等,当BE作为Mysql的从属库时,需指定Mysql Repo的相关配置,详情如示例。
返回值:
- error: 正常执行返回nil, 否则返回有效error对象
示例 1.1: 创建一个带有两个正排列,以及两个向量索引列的集合
fun createCollctionDemo(client *ProximaSearchClient) {
// Create collection with no attached repository
config := &sdk.CollectionConfig{
CollectionName: "example",
MaxDocsPerSegment: 0, // 0 means unlimited, which is equal max value of system
ForwardColumns: []string{"forward", "forward1"},
Columns: []sdk.ColumnIndex{
{
Name: "column",
IndexType: 0, // 0 means default index, which is sdk.ProximaGraphIndex
DataType: 0, // 0 means default, which is sdk.VectorFP32
Dimension: 8, // Required field, no default value, 0 is not legal argument
ExtraParams: map[string]string{"ef_search": "200"}, // Advanced params
}, {
Name: "column1",
IndexType: sdk.ProximaGraphIndex,
DataType: sdk.VectorFP16, // Index type is fp16, query could be fp32 for lack of language types
Dimension: 128,
ExtraParams: map[string]string{},
},
},
Repository: nil, // No repository attached
}
if err = client.CreateCollection(config); err != nil {
log.Fatal("Can't create collection.", err)
}
log.Print("Create collection succeed.")
}
示例 1.2: 创建一个带有两个正排列、单个向量索引列、以及Mysql Repo的集合
fun createCollctionWithRepoDemo(client *ProximaSearchClient) {
// Create collection with attached repository
config := &sdk.CollectionConfig{
CollectionName: "example_with_repo",
MaxDocsPerSegment: 0, // 0 means unlimited, which is equal max value of system
ForwardColumns: []string{"forward", "forward1"},
Columns: []sdk.ColumnIndex{{
Name: "column1",
IndexType: 0, // 0 means default index, which is sdk.ProximaGraphIndex
DataType: 0, // 0 means default, which is sdk.VectorFP32
Dimension: 512, // Required field, no default value, 0 is not legal argument
ExtraParams: map[string]string{"ef_search": "200"}, // Advanced params
},
},
Repository: &sdk.DatabaseRepository{
Repository: sdk.Repository{
Name: "mysql_repo",
Type: sdk.Database,
},
Connection: "mysql://host.com:8080/mysql_database", // JDBC connection uri
TableName: "table_name", // Table name
User: "root", // User name
Password: "root", // Password
},
}
if err = client.CreateCollection(config); err != nil {
log.Fatal("Can't create collection.", err)
}
log.Print("Create collection with attached mysql repository succeed.")
}
2.2. 获取集合配置信息
DescribeCollection(name string) (*CollectionInfo, error)
获取参数name指定的集合配置信息
参数说明:
- name: string指定集合名称
返回值:
- CollectionInfo: 指向CollectionInfo的指针,成功返回时该参数非nil, 失败时通过error参数判定失败原因
- error: 失败返回非nil
示例 2.1: 获取集合配置信息
fun describeCollectionDemo(client *ProximaSearchClient) {
// Retrieve collection named by 'example_with_repo'
info, err = client.DescribeCollection("example_with_repo")
if err != nil {
log.Fatal("Lost collection named by 'example_with_repo', which created before.", err)
}
log.Printf("Collection(With Repository): %+v\n", info)
// Delete collection
if err = client.DropCollection("example_with_repo"); err != nil {
log.Fatal("Failed to drop collection,", err)
}
log.Print("Drop collection succeed.")
}
2.3. 删除指定集合
DropCollection(name string) error
删除指定集合,集合名由参数name指定
参数说明:
- name: string指定集合名称
返回值:
- error: 失败返回非nil
示例 3.1: 删除集合
fun dropCollectionDemo(client *ProximaSearchClient) {
client.DropCollection("example_with_repo")
if err = client.CreateCollection(config); err != nil {
log.Fatal("Can't create collection.", err)
}
log.Print("Create collection with attached mysql repository succeed.")
}
2.4. 获取集合统计信息
StatCollection(string) (*CollectionStat, error)
获取参数指定的集合统计信息,执行成功返回指向CollectionStat的有效指针,失败返回error
参数说明:
- string: 指定集合名称
返回值:
- *CollectionStat: Collection的统计信息
- error: 失败返回非nil
示例 4.1: 获取集合统计信息
fun statCollectionDemo(client *ProximaSearchClient) {
stat, err := client.StatCollection("example")
if err != nil {
log.Fatal("Stat collection failed.", err)
}
log.Printf("Collection Stat: %+v", stat)
}
2.5. 获取集合列表
ListCollections(filters …ListCollectionFilter) ([]*CollectionInfo, error)
获取符合条件的集合列表,执行成功返回CollectionInfo的列表,失败返回error
参数说明:
- ListCollectionFilter: 过滤器对象,过滤器可采用生成器自动生成,可选的生成器如下: - ByRepo(repo string): 包含指定repo名称的Collection
返回值:
- []*CollectionInfo: CollectionInfo列表
- error: 失败返回非nil
示例 5.1: 获取集合列表
fun listCollectionsDemo(client *ProximaSearchClient) {
// List all collections
collections, err := client.ListCollections()
if err != nil {
log.Fatal("Can't retrieve collections from Proxima Server.", err)
}
log.Printf("Collections (%d): \n", len(collections))
for _, collection := range collections {
log.Printf("%+v\n", collection)
}
// List all collections by Repo
collections, err = client.ListCollections(sdk.ByRepo("repo"))
if err != nil {
log.Fatal("Can't retrieve collections from Proxima Server.", err)
}
log.Printf("Collections (%d): \n", len(collections))
for _, collection := range collections {
log.Printf("%+v\n", collection)
}
}
3. 文档管理
文档管理整合为一个通用接口Write, 通过接口参数描述所需的操作,接口定义如下:
Write(*WriteRequest) error
向BE中批量写入文档操作请求,执行成功后返回nil, 否则返回值error中描述了错误信息
参数说明:
- WriteRequest: 写入请求内容
// Row record
type Row struct {
// Primary key of row record
PrimaryKey uint64
// Operation type
OperationType
// Index column value list
IndexColumnValues []interface{}
// Forward column value list
ForwardColumnValues []interface{}
// Log Sequence Number context
*LsnContext
}
// RowMeta meta for row records
type RowMeta struct {
// Index column name list
IndexColumnNames []string
// Index column name list
ForwardColumnNames []string
}
// WriteRequest object, the parameter of ProximaBEClient.Write method
type WriteRequest struct {
// Name of collection
CollectionName string
// Meta header
Meta RowMeta
// Row record list
Rows []Row
// Request ID, Optional
RequestID string
// Magic number, Optional
MagicNumber uint64
}
Write API中根据传入参数的 Row.OperationType 判定当前数据是插入、删除、更新中的某种操作类型,可选的OperationType列表如下:
- **Insert: ** 新增文档
- Update: 更新文档
- Delete: 删除文档
返回值:
- error: 失败返回非nil
3.1. 文档插入
指定Row.OperationType为OPInsert可完成文档的插入操作
示例 1.1: 文档插入
fun insertDocumentDemo(client *ProximaSearchClient) {
rows := &sdk.WriteRequest{
CollectionName: "example",
Meta: sdk.RowMeta{
IndexColumnNames: []string{"column"},
ForwardColumnNames: []string{"forward", "forward1"},
},
Rows: []sdk.Row{
{
PrimaryKey: 0,
OperationType: sdk.Insert,
ForwardColumnValues: []interface{}{1, float32(1.1)},
IndexColumnValues: []interface{}{ // Data type should same with index created before
[]float32{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0},
},
LsnContext: nil, // With empty context
},
},
RequestID: "", // Optional field
MagicNumber: 0, // Optional field
}
// Write rows to collection
err = client.Write(rows)
if err != nil {
log.Fatal("Insert data to collection failed.", err)
}
}
3.2. 文档更新
指定Row.OperationType为OPUpdate可完成文档的更新操作
示例 2.1:更新文档
fun updateDocumentDemo(client *ProximaSearchClient) {
rows := &sdk.WriteRequest{
CollectionName: "example",
Meta: sdk.RowMeta{
IndexColumnNames: []string{"column"},
ForwardColumnNames: []string{"forward", "forward1"},
},
Rows: []sdk.Row{
{
PrimaryKey: 0,
OperationType: sdk.Update,
ForwardColumnValues: []interface{}{2, float32(2.2)},
IndexColumnValues: []interface{}{ // Data type should same with index created before
[]float32{21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0},
},
LsnContext: &sdk.LsnContext{ // With valid context
LSN: 0,
Context: "write context hear",
},
}},
RequestID: "", // Optional field
MagicNumber: 0, // Optional field
}
// Write rows to collection
err = client.Write(rows)
if err != nil {
log.Fatal("Insert data to collection failed.", err)
}
}
3.3. 文档删除
指定Row.OperationType为OPDelete可完成文档的删除操作
示例 3.1:删除文档
fun deleteDocumentDemo(client *ProximaSearchClient) {
rows := &sdk.WriteRequest{
CollectionName: "example",
Meta: sdk.RowMeta{
IndexColumnNames: []string{"column"},
ForwardColumnNames: []string{"forward", "forward1"},
},
Rows: []sdk.Row{
{
PrimaryKey: 0,
OperationType: sdk.Delete,
},
},
RequestID: "", // Optional field
MagicNumber: 0, // Optional field
}
// Write rows to collection
err = client.Write(rows)
if err != nil {
log.Fatal("Insert data to collection failed.", err)
}
}
3.4. 批量文档操作
请求中包含多行数据,并指定OperationType完成批量文档操作
示例 4.1:批量文档操作
fun batchDocumentOperationDemo(client *ProximaSearchClient) {
rows := &sdk.WriteRequest{
CollectionName: "example",
Meta: sdk.RowMeta{
IndexColumnNames: []string{"column"},
ForwardColumnNames: []string{"forward", "forward1"},
},
Rows: []sdk.Row{
{
PrimaryKey: 0,
OperationType: sdk.Insert,
ForwardColumnValues: []interface{}{1, float32(1.1)},
IndexColumnValues: []interface{}{ // Data type should same with index created before
[]float32{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0},
},
LsnContext: nil, // With empty context
}, {
PrimaryKey: 2,
OperationType: sdk.Insert,
ForwardColumnValues: []interface{}{2, float32(2.2)},
IndexColumnValues: []interface{}{ // Data type should same with index created before
[]float32{21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0},
},
LsnContext: &sdk.LsnContext{ // With valid context
LSN: 0,
Context: "write context hear",
},
}},
RequestID: "", // Optional field
MagicNumber: 0, // Optional field
}
// Write rows to collection
err = client.Write(rows)
if err != nil {
log.Fatal("Insert data to collection failed.", err)
}
}
4. 文档查询
4.1. 向量查询
Query(collection string, column string, features interface{}, opts …QueryOption) (*QueryResponse, error)
单次、批量向BE发起向量查询请求,执行成功返回QueryResponse的有效指针,失败返回error
参数说明:
- collection: string指定集合名称
- column: string指定列名
- features: 指定查询向量,该参数可以是切片、数组、或者二维矩阵(每行一个向量),向量中的原始数据类型支持int8/uint32/uint64/float32中的一种(由于语言限制,如果索引创建时数据类型配置为DTVectorFP16,请使用float32类型与BE交互,服务器端会自动进行类型转换)
- opts: QueryOption可选参数列表,可选的参数如下:
- WithTopK(int): 最近的邻居个数
- WithRadius(float32): 搜索半径,可选区间为0~1的浮点数,越大召回效果上升、性能下降,越小召回效果下降、性能上升。当请求中同时打开暴力匹配选项,则此参数无效。
- WithLinearSearch(): 暴力匹配选项,返回的为绝对topk结果(性能最低)
- WithDebugMode(): 调试模式,将详细搜索的各阶段统计数据返回(不建议生产环境中打开)
- WithParam(string, interface{}): 高级检索参数,可选配置项待发布
返回值:
- *QueryResponse: 最近邻的documents结果
- error: 失败返回非nil
示例 1.1: 单次向量查询
fun queryDemo(client *ProximaSearchClient) {
// Query one vector
resp, err := client.Query("example", "column", []float32{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0}, sdk.WithTopK(10))
if err != nil {
log.Fatal("Query failed.", err)
}
log.Printf("Response: %+v\n", resp)
}
示例 1.2: 批量向量查询
fun batchQueryDemo(client *ProximaSearchClient) {
// Query with matrix
resp, err = client.Query("example", "column",
[][]float32{{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0},
{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0},
{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0},
{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0},
},
sdk.WithTopK(10),
sdk.WithDebugMode(), // Enable debug mode, do not recommend on product environments
sdk.WithRadius(1.5), // Search radius, no effect if sdk.WithLinearSearch enabled
sdk.WithLinearSearch(), // Enable linear search
sdk.WithParam("customize_param", 10),
sdk.WithParam("customize_param2", 1.0),
sdk.WithParam("customize_param3", "str"))
if err != nil {
log.Fatal("Query failed.", err)
}
log.Printf("Response: %+v\n", resp)
}
4.2. 主键查询
GetDocumentByKey(collection string, primaryKey uint64) (*Document, error)
通过文档主键获取文档,执行成功返回Document的有效指针,失败返回error
参数说明:
- collection: 集合名称
- primaryKey: 文档主键
返回值:
- *Document: 文档对象
- error: 失败返回非nil
示例 2.1: 根据文档主键获取文档内容
fun queryDocByPKDemo(client *ProximaSearchClient) {
// Retrieve document by primary key
doc, err := client.GetDocumentByKey("example", 0)
if err != nil {
log.Fatal("Failed to retrieve document from server.", err)
}
log.Printf("Document: %+v\n", doc)
}