这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

SDK 手册

介绍 Proxima Bilin Engine 所提供的 SDK,目前支持的语言有:C++、Golang、Java 和 Python 等。

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为删除时不需要指定。支持三种类型
  • 向量list,如[1.0, 2.0, 3.0]
  • json数组str,如"[1.0,2.0,3.0]"
  • bytes,必须为小端字节序。
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 特征,支持三种类型
  • 小端字节序的bytes
  • json数组字符串,支持打平或者嵌套json数组。如2个batch的2维向量,既可以写"[1.0,2.0,3.0,4.0]“也可以写”[[1.0,2.0],[3.0,4.0]]"
  • 向量列表,如[[5.1, 3.5, 1.4, 0.2], [5.5, 2.3, 4.0, 1.3]]
data_type 数据类型,DataType 类型。默认为空。
  • bytes类型的特征允许为空,使用集合创建时的数据类型。
  • 向量列表类型的特征时必须设置。
dimension 向量维度,int类型。默认为空。
  • bytes类型的特征必须设置。
  • 向量列表类型的特征时支持自动推导。
batch_count batch大小,int类型。默认为空。
  • bytes类型的特征必须设置。
  • 向量列表类型的特征支持自动推导。
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类型。
返回值有两个

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类型,IndexColumnParam类型参数见下表
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操作时,不需要指定,支持三种格式:
  • 向量数组,如[1.0, 2.0, 3.0]
  • json数组str,如"[1.0,2.0,3.0]"
  • bytes,必须为小端字节序。
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 查询的特征,可以是单个或者多个向量,支持三种类型:
  • 小端字节序的bytes
  • json数组字符串,支持嵌套json数组。如2个batch的2维向量,可以写为"[[1.0,2.0],[3.0,4.0]]"
  • 向量列表,如[[5.1, 3.5, 1.4, 0.2], [5.5, 2.3, 4.0, 1.3]]
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)

}