Springboot整合Milvus向量库

1. Milvus的Maven依赖, 配置如下

        <dependency><groupId>io.milvus</groupId><artifactId>milvus-sdk-java</artifactId><version>2.3.4</version><exclusions><exclusion><artifactId>log4j-slf4j-impl</artifactId><groupId>org.apache.logging.log4j</groupId></exclusion></exclusions></dependency>

PS: 请注意!引入的版本要看你部署的milvus服务的版本是多少,然后milvus官网上会有milvus服务对应的java sdk版本的版本号,版本号一定要对应的上  这样相应的版本api文档接口才可以用

milvus官方文档:Milvus v2.3.x documentation

然后2.3.4版本的java sdk的milvus还需要引用google 的protobuf包,不然会报错提示找不到此包

此包也要注意对应milvus的版本  这里官网没说明,我自行尝试可用的是3.24.1版本对应milvus的2.3.4版本的, 配置如下:

        <dependency><groupId>com.google.protobuf</groupId><artifactId>protobuf-java</artifactId><version>3.24.1</version></dependency>

2. 向量库的配置类 获取向量库服务地址 登录用户密码等

import io.milvus.client.MilvusServiceClient;
import io.milvus.param.ConnectParam;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MilvusConfig {@Value("${milvus.host}")private String host;@Value("${milvus.port}")private Integer port;@Value("${milvus.username}")private String username;@Value("${milvus.password}")private String password;@Beanpublic MilvusServiceClient milvusServiceClient() {return new MilvusServiceClient(ConnectParam.newBuilder().withHost(host).withPort(port).withAuthorization(username, password).build());}
}

application.yml配置文件里配置相应的数据信息

3. 根据milvus 2.3.5 java SDK提供的API接口  调测相关使用的接口 

如:创建集合,创建索引,加载集合到内存,插入向量数据,查询向量数据并返回结果 删除集合

import java.util.List;/*** milvus向量数据库相关业务接口** @author Jx* @version 2024-3-18*/
public interface IMilvusService {Boolean hasCollect(String collectionName);void create(String collectionName, String desc);Boolean insert(String name, List<Long> textIds, List<List<Float>> vectorList);List<Long> search(String name, int topK, List<List<Float>> vectorList);void dropCollect(String name);void createIndex(String name);void dropVectors(String name, List<Long> indexIds);
}

实现类

import com.beust.jcommander.internal.Lists;
import com.geb.config.FaceArchive;
import com.geb.service.IMilvusService;
import io.milvus.client.MilvusServiceClient;
import io.milvus.common.clientenum.ConsistencyLevelEnum;
import io.milvus.grpc.DataType;
import io.milvus.grpc.GetLoadStateResponse;
import io.milvus.grpc.MutationResult;
import io.milvus.grpc.SearchResults;
import io.milvus.param.IndexType;
import io.milvus.param.MetricType;
import io.milvus.param.R;
import io.milvus.param.RpcStatus;
import io.milvus.param.collection.*;
import io.milvus.param.dml.DeleteParam;
import io.milvus.param.dml.InsertParam;
import io.milvus.param.dml.SearchParam;
import io.milvus.param.highlevel.collection.ListCollectionsParam;
import io.milvus.param.highlevel.collection.response.ListCollectionsResponse;
import io.milvus.param.highlevel.dml.DeleteIdsParam;
import io.milvus.param.highlevel.dml.response.DeleteResponse;
import io.milvus.param.index.CreateIndexParam;
import io.milvus.response.SearchResultsWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.List;
import java.util.Map;@Slf4j
@Service
public class MilvusServiceImpl implements IMilvusService {@Autowiredprivate MilvusServiceClient milvusServiceClient;final IndexType INDEX_TYPE = IndexType.IVF_FLAT;   // IndexTypefinal String INDEX_PARAM = "{\"nlist\":1024}";     // ExtraParam/*** 创建集合的字段* text_id  对应的文本id* vector  向量字段* tag  标签*/private final String TEXTID = "text_id";private final String VECTOR = "vector";private final String TAG = "tag";private final int dimension = 1024;/*** 创建集合  指定集合名称*/@Overridepublic void create(String collectionName, String desc){log.info("Miluvs create collectionName:{}, desc:{}", collectionName, desc);boolean has = hasCollect(collectionName);log.info("Miluvs hasCollect:{}", has);// 不存在此集合才进行创建集合if(!has){//  创建集合 设置索引 加载集合到内存中FieldType fieldType1 = FieldType.newBuilder().withName(TEXTID).withDataType(DataType.Int64).withPrimaryKey(true).withAutoID(false).build();FieldType fieldType2 = FieldType.newBuilder().withName(VECTOR)  // 设置向量名称.withDataType(DataType.FloatVector)  // 设置向量类型.withDimension(dimension) // 设置向量维度.build();FieldType fieldType3 = FieldType.newBuilder().withName(TAG).withDataType(DataType.Int64).build();CreateCollectionParam createCollectionReq = CreateCollectionParam.newBuilder().withCollectionName(collectionName).withDescription(desc).withShardsNum(2).addFieldType(fieldType1).addFieldType(fieldType2).addFieldType(fieldType3).withEnableDynamicField(true).withConsistencyLevel(ConsistencyLevelEnum.BOUNDED).build();R<RpcStatus> response = milvusServiceClient.createCollection(createCollectionReq);if (response.getStatus() != R.Status.Success.getCode()) {log.info("milvus create fail message:{}", response.getMessage());}else{// 创建集合索引并加载集合到内存  插入数据和搜索的前置操作!!createIndex(collectionName);}}}/*** 创建集合索引 -- 加在向量字段上* @param collectionName*/public void createIndex(String collectionName){milvusServiceClient.createIndex(CreateIndexParam.newBuilder().withCollectionName(collectionName).withFieldName(VECTOR).withIndexType(INDEX_TYPE).withMetricType(MetricType.L2).withExtraParam(INDEX_PARAM).withSyncMode(Boolean.FALSE).build());// 加载所创建的集合loadCollection(collectionName);}/*** 加载集合* @param collectionName*/public void loadCollection(String collectionName){milvusServiceClient.loadCollection(LoadCollectionParam.newBuilder().withCollectionName(collectionName).build());// You can check the loading statusGetLoadStateParam param = GetLoadStateParam.newBuilder().withCollectionName(collectionName).build();R<GetLoadStateResponse> stateResponse = milvusServiceClient.getLoadState(param);if (stateResponse.getStatus() != R.Status.Success.getCode()) {System.out.println(stateResponse.getMessage());}}/*** 集合是否存在* @return*/@Overridepublic Boolean hasCollect(String collectionName){R<Boolean> hasResult = milvusServiceClient.hasCollection(HasCollectionParam.newBuilder().withCollectionName(collectionName).build());if (hasResult.getStatus() == R.Status.Success.getCode()) {return hasResult.getData();}return false;}/*** 向量库中插入数据*/@Overridepublic Boolean insert(String name, List<Long> textIds, List<List<Float>> vectorList){log.info("milvus insert name:{}, textIds:{}, vectorList:{}", name, textIds, vectorList);List<Long> tagList = new ArrayList<>();for (Long textId : textIds) {tagList.add(0L);}List<InsertParam.Field> fieldsInsert = new ArrayList<>();fieldsInsert.add(new InsertParam.Field(TEXTID, textIds));  // 文本对应的ids数据listfieldsInsert.add(new InsertParam.Field(VECTOR, vectorList));  // 转换后的向量数据listfieldsInsert.add(new InsertParam.Field(TAG, tagList));  // 标签占位符  给个0InsertParam param = InsertParam.newBuilder().withCollectionName(name).withFields(fieldsInsert).build();R<MutationResult> response = milvusServiceClient.insert(param);if (response.getStatus() != R.Status.Success.getCode()) {log.info("milvus insert vector fail! message:{}", response.getMessage());return false;}else{return true;}}/*** 删除集合* @param collectionName*/@Overridepublic void dropCollect(String collectionName){milvusServiceClient.dropCollection(DropCollectionParam.newBuilder().withCollectionName(collectionName).build());}/*** 根据ids删除向量* @param collectionName* @param indexIds*/@Overridepublic void dropVectors(String collectionName, List<Long> indexIds){String expr =  TEXTID + " in " + indexIds;DeleteParam param = DeleteParam.newBuilder().withCollectionName(collectionName).withExpr(expr).build();R<MutationResult> response = milvusServiceClient.delete(param);if (response.getStatus() != R.Status.Success.getCode()) {System.out.println(response.getMessage());}}/*** 向量搜索 - 向量库中用具体向量搜索 - 返回indexIds*/@Overridepublic List<Long> search(String collectionName, int topK , List<List<Float>> vectorList){// 构建查询条件  进行向量字段查询   待测试1024维度向量SearchParam searchParam = io.milvus.param.dml.SearchParam.newBuilder().withCollectionName(collectionName).withVectorFieldName(VECTOR).withOutFields(Lists.newArrayList("*")).withVectors(vectorList).withTopK(topK).build();R<SearchResults> searchResults = milvusServiceClient.search(searchParam);if (searchResults.getStatus() != R.Status.Success.getCode()) {log.info(searchResults.getMessage());}List<Long> textIdList = new ArrayList<>() ;SearchResultsWrapper wrapper = new SearchResultsWrapper(searchResults.getData().getResults());for (int i = 0; i < vectorList.size(); ++i) {List<SearchResultsWrapper.IDScore> scores = wrapper.getIDScore(i);for (SearchResultsWrapper.IDScore score:scores) {Map<String, Object> filedsMap = score.getFieldValues();textIdList.add(Long.valueOf(String.valueOf(filedsMap.get(TEXTID))));}}return textIdList;}/*** 删除集合中的 id对应的向量*/public void deleteEmbedingById(){List<String> ids = Lists.newArrayList("441966745769900131","441966745769900133");DeleteIdsParam param = DeleteIdsParam.newBuilder().withCollectionName(FaceArchive.COLLECTION_NAME_MILVUS_TESTONE).withPrimaryIds(ids).build();R<DeleteResponse> response = milvusServiceClient.delete(param);if (response.getStatus() != R.Status.Success.getCode()) {System.out.println(response.getMessage());}for (Object deleteId : response.getData().getDeleteIds()) {System.out.println(deleteId);}}// 测试用的向量数据类型public List<List<Float>> getListVector(){List<Float> vectorData = new ArrayList<>();for (int i = 0; i < 1; i++) {vectorData.add((float) Math.random());}List<List<Float>> vectors = new ArrayList<>();vectors.add(vectorData);return vectors;}
}

以上,跟业务进行结合  直接调用操作向量库的API接口即可~

PS:milvus  集成在springboot项目中踩的坑:

#首先就是milvus和protobuf的版本要对应上  可以查下官网api提供的服务端的milvus版本对应的java sdk milvus版本    然后根据milvus sdk版本再找到对应的protobuf版本

#其次  根据官网文档api创建完集合后是无法自动加载集合的  需要手动为集合创建一个索引  比如IVF类型的索引  再进行集合加载到内存  然后才可以对该集合查询插入数据等操作

插入过程中: 所有字段值都不能为空 且 所有字段值条数都需一样  也就是统一字段条数  一致!!

#还有就是,创建集合时候  确定好向量字段的维度,

后面插入向量数据以及查询向量数据的数据维度要与创建向量字段的维度相同!!

注意! milvus向量库只负责向量的操作存储及查询这些,并不负责文本or视频音频转为向量数据的过程,此过程需要专门模型转换进行数据处理为向量数据才可用milvus向量数据库操作!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/588690.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis的5大常见数据类型的用法

上一篇文章我们讲了Redis的10大应用场景&#xff0c;这一篇文章就针对Redis的常用数据结构进行一个说明&#xff0c;通过示例的形式演示每一种数据结构如何使用。 当涉及Redis的数据操作时&#xff0c;不同数据类型对应的不同数据结构&#xff0c;如下就对5大常用的数据类型进行…

三台电机的顺启逆停

1&#xff0c;开启按钮输入信号是 电机一开始启动&#xff0c;5秒回电机2启动 &#xff0c;在5秒电机三启动 关闭按钮输入时电机3关闭 &#xff0c;5秒后电机2关闭 最后电机一关闭 2&#xff0c;思路开启按钮按下接通电机1 并且接通定时器T0 定时器T0 到时候接通电机2 并且开…

【漏洞复现】WordPress Plugin LearnDash LMS 敏感信息暴漏

漏洞描述 WordPress和WordPress plugin都是WordPress基金会的产品。WordPress是一套使用PHP语言开发的博客平台。该平台支持在PHP和MySQL的服务器上架设个人博客网站。WordPress plugin是一个应用插件。 WordPress Plugin LearnDash LMS 4.10.2及之前版本存在安全漏洞&#x…

vCenter Server出现no healthy upstream的解决方法

https://blog.51cto.com/wangchunhai/4907250 访问vCenter 7.0 地址后&#xff0c;页面出现“no healthy upstream”,无法正常登录vCenter&#xff0c;重启后依旧如此&#xff0c;该故障的前提是没有对vCenter做过任何配置&#xff0c;如下图所示。 尝试登录"VMware vCen…

天龙八部_暗黑机制_人面桃花_单机架设搭建

一. 搭建成功视频演示 天龙八部_暗黑机制_人面桃花_单机架设搭建 二. 一些文件截图 完整教程和搭建文件获取: https://githubs.xyz/y24.html 三. 搭建步骤 安装虚拟机虚拟机打开一键端&#xff0c;然后登录root&#xff0c;密码&#xff1a;123456启动./run 脚本 &#xff0…

MATLAB 自定义均值滤波 (53)

MATLAB 自定义均值滤波 (53) 一、算法介绍二、算法实现1.原理2.代码一、算法介绍 均值滤波,是一种常见的点云平滑算法,改善原始点云的数据质量问题,MATLAB自带的工具似乎不太友好,这里提供自定义实现的点云均值滤波算法,具体效果如下所示: 均值滤波前: 均值滤波后:…

电商技术揭秘五:电商平台的个性化营销与数据分析

文章目录 引言1. 个性化营销的概念与价值1.1 个性化营销的定义1.1.1 个性化营销的基本概念1.1.2 个性化营销在电商领域的重要性 1.2 个性化营销的核心价值1.2.1 提升用户体验1.2.2 增加转化率和客户忠诚度1.2.3 优化营销资源配置 2. 用户画像与行为分析2.1 用户画像的构建2.1.1…

人人都离不开的算法:AI 时代的生存指南

文章目录 一、算法在生活中的“无处不在”二、算法在工作学习中的“智慧助力”三、算法在社会发展中的“驱动力量”四、算法带来的“双刃剑”效应五、应对算法挑战的策略《人人都离不开的算法——图解算法应用》编辑推荐1、通俗易懂2、技术科普3、贴近时代、贴近生活4、启发思考…

[C/C++] -- 二叉树

1.简介 二叉树是一种每个节点最多有两个子节点的树结构&#xff0c;通常包括&#xff1a;根节点、左子树、右子树。 满二叉树&#xff1a; 如果一棵二叉树只有度为0的结点和度为2的结点&#xff0c;并且度为0的结点在同一层上&#xff0c;则这棵二叉树为满二叉树。深度为k&a…

对 NGINX、Kong 和 Amazon 的 API 管理解决方案进行基准测试:它们能否交付实时 API?

原文作者&#xff1a;Alessandro Fael Garcia of F5 原文链接&#xff1a;对 NGINX、Kong 和 Amazon 的 API 管理解决方案进行基准测试&#xff1a;它们能否交付实时 API&#xff1f; 转载来源&#xff1a;NGINX 开源社区 NGINX 唯一中文官方社区 &#xff0c;尽在 nginx.org.c…

【Qt】使用Qt实现Web服务器(九):EventSource+JSON实现工业界面数据刷新

1、效果 效果如下,实时刷新温度、湿度 2、源码 2.1 index.html <html><body> <!-- 页面布局,本人对HTML标签不熟悉,凑合看吧 --> <div><label for

智能交通广播系统解决方案

智能交通广播系统解决方案 iP网络广播求助对讲系统在智慧交通中起至关重要的作用。本系统具备公共广播系统一般用途的日常广播(播放背景音乐、话筒寻呼广播)和紧急广播。同时具有背景音乐广播、公共广播、紧急广播、语音求助全双工双向对讲等功能。在出现突发性交通事故或恶劣…