springboot milvus search向量相似度查询 踩坑使用经验
1.前提提要:java的pom 版本为:2.4.9 milvus 版本是:2.4.13-hotfix
2.先来工具类方法
/**
* 向量搜索
* @param client
* @param query
* @return
*/
public SearchResp search(@NonNull MilvusClientV2 client, @NonNull VectorCondition query) {
final List<BaseVector> data = query.getData();
if (CollectionUtils.isEmpty(data)) {
return null;
}
SearchReq.SearchReqBuilder searchReqBuilder = SearchReq.builder().collectionName(query.getCollectionName())
.data(data);
if (query.getTopK() > 0) {
searchReqBuilder.topK(query.getTopK());
}
if (!StringUtils.isEmpty(query.getAnnsField())) {
searchReqBuilder.annsField(query.getAnnsField());
}
if (!CollectionUtils.isEmpty(query.getSearchParams())) {
searchReqBuilder.searchParams(query.getSearchParams());
}
if (!CollectionUtils.isEmpty(query.getPartitionNames())) {
searchReqBuilder.partitionNames(query.getPartitionNames());
}
if (!CollectionUtils.isEmpty(query.getOutputFields())) {
searchReqBuilder.outputFields(query.getOutputFields());
} else {
searchReqBuilder.outputFields(Collections.singletonList("*"));
}
if (StringUtils.isNotBlank(query.getFilter())) {
searchReqBuilder.filter(query.getFilter());
}
final SearchResp search = client.search(searchReqBuilder.build());
return search;
}
3.包装的请求条件
@Data
@Builder
public class VectorCondition {
//现有集合的名称。
@NonNull
String collectionName;
String partitionName;
//分区名称列表。
List<String> partitionNames;
//返回每个实体中包含的字段名称列表。
//该值默认为None。如果未指定,则选择集合中的所有字段作为输出字段。
List<String> outputFields;
//要查询的实体的 ID。
List<Object> ids;
//用于筛选匹配实体的标量筛选条件。
//您可以将此参数设置为空字符串以跳过标量过滤。要构建标量过滤条件,请参阅布尔表达式规则。
String filter;
//目标集合的一致性级别。
//该值默认为创建当前集合时指定的值,选项包括Strong ( 0 )、Bounded ( 1 )、Session ( 2 ) 和Finally ( 3 )。
ConsistencyLevel consistencyLevel;
//查询结果中要跳过的记录数。
//您可以结合使用此参数来limit启用分页。
//该值的总和limit应小于 16,384。
long offset;
//查询结果中返回的记录数。
//您可以结合使用此参数来offset启用分页。
//该值的总和offset应小于 16,384。
long limit;
//矢量字段的名称,当有多个矢量字段时使用。如果只存在一个矢量字段,我们将直接使用它
String annsField;
//搜索结果中返回的记录数。此参数使用与参数相同的语法limit,因此您只应设置其中一个。
//您可以结合使用此参数来offset启用分页。
//该值的总和offset应小于 16,384。
int topK;
//向量嵌入的列表。
//Milvus 搜索与指定的向量嵌入最相似的向量嵌入。
List<BaseVector> data;
//插入的向量。
List<JsonObject> dataJson;
//Milvus 将计算出的距离四舍五入到的小数位数。
//该值默认为-1,表示 Milvus 跳过对计算距离进行四舍五入并返回原始值。
int roundDecimal;
//此操作特有的参数设置。
//metric_type (字符串)
//应用于此操作的度量类型。这应该与索引上面指定的矢量字段时使用的类型相同。
//可能的值是L2、IP和COSINE。
//半径(浮点数)
//确定最小相似度的阈值,设置metric_type为时L2,确保该值大于range_filter的值,否则,该值应小于range_filter的值。
//范围过滤器(浮点数)
//将搜索范围缩小到特定相似度范围内的向量。设置metric_type为IP或 时COSINE,请确保此值大于 radius 。否则,此值应小于radius。
Map<String, Object> searchParams;
//是否在相似性搜索期间忽略增长的片段。
boolean ignoreGrowing;
//设置字段名称以对结果进行分组。
String groupByFieldName;
}
4.向量数据的转换
final List<Object> data;
// 使用Stream API进行转换
List<Float> floatList = data.stream()
.map(obj -> obj instanceof Double ? ((Double) obj).floatValue() : (Float) obj) // 转换为Float
.collect(Collectors.toList()); // 收集结果到新的列表
List<BaseVector> requestData = new ArrayList<>();
final FloatVec baseVector = new FloatVec(floatList);
requestData.add(baseVector);
Map<String, Object> params = new HashMap<>();
params.put("nprobe", "1024");
params.put("radius", 0.5f);
final VectorCondition vector = VectorCondition.builder()
.collectionName("xxxxx")
.annsField("vector")
.topK(1)
.searchParams(params)
.data(requestData)
.build();
SearchResp searchR = (SearchResp) milvusUtil.execute("search", vector);
final List<List<SearchResp.SearchResult>> searchResults = searchR.getSearchResults();
for (List<SearchResp.SearchResult> results : searchResults) {
for (SearchResp.SearchResult result : results) {
System.out.printf("ID: %s, Score: %f, %s\n", result.getId(), result.getScore(), result.getEntity().toString());
}
}
使用线程池获取MilvusClient连接对象,具体可看之前的博客
case MilvusUtil.SEARCH:
result = this.search(milvusClientPool.getClient(SEARCH), vectorCondition);
break;
报错
Caused by: java.lang.ClassNotFoundException: com.google.gson.ToNumberPolicy
原因:java.lang.ClassNotFoundException:com.google.gson.ToNumberPolicy
和上次使用的经验一样,肯定没有最新的包,果然,换成最新的谷歌的包问题解决
<!--milvus-->
<dependency>
<groupId>io.milvus</groupId>
<artifactId>milvus-sdk-java</artifactId>
<version>2.4.9</version>
<exclusions>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
<exclusion>
<artifactId>gson</artifactId>
<groupId>com.google.gson</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>26.0-jre</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.9</version> <!-- 或者更新版本 -->
</dependency>