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>

在这里插入图片描述

### Milvus 向量数据库中的向量相似度计算 Milvus 是一个专注于高效管理与查询大规模向量数据的开源数据库,其核心能力之一便是通过高效的算法实现向量之间的相似度计算。以下是关于 Milvus 中如何实现向量相似度计算的具体介绍。 #### 1. 支持的相似度计算方法 Milvus 提供了多种用于衡量向量之间相似性的距离度量方法,主要包括欧几里得距离 (L2 距离) 和余弦相似度两种主要方式[^1]: - **欧几里得距离 (Euclidean Distance)** L2 距离是一种常见的几何距离测量方法,适用于低维度到中等维度的数据集。对于两个 n 维向量 \( A \) 和 \( B \),它们的距离定义为: \[ d(A, B) = \sqrt{\sum_{i=1}^{n}(A_i - B_i)^2} \] 此种方法适合于需要精确匹配的应用场景。 - **余弦相似度 (Cosine Similarity)** 该方法主要用于评估两向量方向上的接近程度,而不考虑模长差异。具体公式如下所示: \[ sim(A, B) = \frac{A \cdot B}{\|A\|\|B\|} \] 它广泛应用于文本检索、推荐系统等领域,在高维稀疏空间表现尤为突出[^2]。 #### 2. 实现流程概述 为了提高搜索效率并降低资源消耗,Milvus 并不会直接针对原始输入执行暴力穷举操作来寻找最邻近点;而是采用了一些优化策略和技术手段完成整个过程: - 数据预处理阶段会先将待索引对象转换成固定长度数值型特征表示形式; - 接着运用 ANN(Approximate Nearest Neighbor) 近似最近邻查找框架加速定位潜在候选集合; - 最终再依据选定的距离函数逐一验证剩余候选项得出最终结果列表。 下面是基于 Python SDK 使用 Milvus 执行一次简单向量相似性搜索的例子演示代码片段: ```python from milvus import Milvus, IndexType, MetricType # 创建连接实例 client = Milvus(host='localhost', port='19530') # 插入测试数据 vector_dim = 128 data = [[random.random() for _ in range(vector_dim)] for __ in range(10)] status, ids = client.insert(collection_name="example_collection", records=data) # 构建索引结构 index_param = {'nlist': 16384} status = client.create_index( collection_name="example_collection", index_type=IndexType.IVF_FLAT, params=index_param, metric_type=MetricType.L2 ) # 查询部分样本对应的 kNN 结果 search_params = {"nprobe": 16} results = client.search( collection_name="example_collection", query_records=[[random.random() for _ in range(vector_dim)]], top_k=5, params=search_params ) print(results) ``` 此脚本展示了从建立客户端链接直至发起实际请求获取前五名相近项的整体逻辑链条。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT_Octopus

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值