SpringBoot集成Milvus,实现数据增删改查

news/2025/2/12 22:58:45/
aidu_pl">

Milvus是一款开源向量数据库,主要用于在大模型领域做向量查询的相关操作。milvus支持的语言比较多,支持python, Java, Go,node等开发语言本文主要介绍如何使用Java语言,采用springboot框架集成和调用Milvus数据库。

本文示例使用的milvus版本是 v2.5.4关于如何安装部署milvus向量数据,请参考上一篇文章:https://lowcode.blog.csdn.net/article/details/145552128

本文使用Java sdk操作Milvus实现数据的增删改查,需要先对milvus的基本概念有个初步的了解,便于对后面代码的更好理解。milvus更多帮助请参考官方文档:https://milvus.io/docs/overview.md

1、Milvus基本概念

  • 数据库Database与传统的数据库引擎MySQL类似,你也可以在 Milvus 中创建数据库,并为特定用户分配权限来管理它们。然后,此类用户有权管理数据库中的集合。一个 Milvus 集群最多支持 64 个数据库。Milvus 集群附带一个名为 'default' 的默认数据库。除非另有指定,否则将在 default 数据库中创建集合。
  • 集合Collection 在 Milvus 中,你可以创建多个集合来管理数据,并将数据作为实体插入到集合中。Collection 和 entity 类似于关系数据库中的 table 和 records集合是具有固定列和变体行的二维表。每列表示一个字段,每行表示一个实体。Collection 是具有固定列和变体行的二维表。每列表示一个字段,每行表示一个实体。需要Schema来实现此类结构数据管理要插入的每个实体都必须满足Schema中定义的约束。
  • 实体Entity :在 Milvus 中,Entity 是指 Collection 中共享相同 Schema 的数据记录,一行中每个字段的数据构成一个 Entity。因此,同一 Collection 中的 Entities 具有相同的属性(例如字段名称、数据类型和其他约束)。将 Entity 插入 Collection 时,要插入的 Entity 只有在包含 Schema 中定义的所有字段时才能成功添加。Milvus 还支持动态字段,以保持 Collection 的可扩展性。启用动态字段后,您可以将 Schema 中未定义的字段插入到 Collection 中。这些字段和值将作为键值对存储在名为 $meta 的保留字段中。

2、添加maven依赖

创建springboot工程后,在pom.xml文件里引入milvus的sdk

<dependency><groupId>io.milvus</groupId><artifactId>milvus-sdk-java</artifactId><version>2.5.4</version>
</dependency>

本示例使用的是milvus2.5.4最新版本,Java sdk 接口参考文档:https://milvus.io/api-reference/java/v2.5.x/About.md

注意使用sdk版本跟milvus版本的对应关系,milvus2.5.x版本建议使用sdk2.5.2以上版本,否则可能会出现一些诡异问题。

3、配置yml文件

#配置milvus向量数据库的IP和端口,后面构建MilvusClient时需要

server:port: 8080
milvus:host: 192.168.3.17port: 19530

4、创建MilvusClient初始化类

import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
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;@Beanpublic MilvusClientV2 milvusClientV2() {String uri = "http://"+host+":"+port;ConnectConfig connectConfig = ConnectConfig.builder().uri(uri).build();return new MilvusClientV2(connectConfig);}
}

5、创建操作向量库的Seivce

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.yuncheng.milvus.TestRecord;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.common.DataType;
import io.milvus.v2.common.IndexParam;
import io.milvus.v2.service.collection.request.AddFieldReq;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
import io.milvus.v2.service.vector.request.GetReq;
import io.milvus.v2.service.vector.request.InsertReq;
import io.milvus.v2.service.vector.request.SearchReq;
import io.milvus.v2.service.vector.request.data.FloatVec;
import io.milvus.v2.service.vector.response.GetResp;
import io.milvus.v2.service.vector.response.InsertResp;
import io.milvus.v2.service.vector.response.SearchResp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;@Component
public class MilvusDemoService {private static final Logger log = LoggerFactory.getLogger(MilvusDemoService.class);//类似于mysql中的表,定义一个名称为collection_01的集合private static final String COLLECTION_NAME = "collection_01";//为了测试验证方便,向量维度定义2private static final int VECTOR_DIM = 2;private final MilvusClientV2 client;public MilvusDemoService(MilvusClientV2 client) {this.client = client;}/*** 创建一个Collection*/public void createCollection() {CreateCollectionReq.CollectionSchema schema = client.createSchema();schema.addField(AddFieldReq.builder().fieldName("id").dataType(DataType.VarChar).isPrimaryKey(true).autoID(false).build());schema.addField(AddFieldReq.builder().fieldName("title").dataType(DataType.VarChar).maxLength(10000).build());schema.addField(AddFieldReq.builder().fieldName("title_vector").dataType(DataType.FloatVector).dimension(VECTOR_DIM).build());IndexParam indexParam = IndexParam.builder().fieldName("title_vector").metricType(IndexParam.MetricType.COSINE).build();CreateCollectionReq createCollectionReq = CreateCollectionReq.builder().collectionName(COLLECTION_NAME).collectionSchema(schema).indexParams(Collections.singletonList(indexParam)).build();client.createCollection(createCollectionReq);}/*** 往collection中插入一条数据*/public void insertRecord(TestRecord record) {JsonObject vector = new JsonObject();vector.addProperty("id", record.getId());vector.addProperty("title", record.getTitle());List<Float> vectorList = new ArrayList<>();//为了模拟测试,向量写死2个vectorList.add(2.8f);vectorList.add(3.9f);Gson gson = new Gson();vector.add("title_vector", gson.toJsonTree(vectorList));InsertReq insertReq = InsertReq.builder().collectionName(COLLECTION_NAME).data(Collections.singletonList(vector)).build();InsertResp resp = client.insert(insertReq);}/*** 通过ID获取记录*/public GetResp getRecord(String id) {GetReq getReq = GetReq.builder().collectionName(COLLECTION_NAME).ids(Collections.singletonList(id)).build();GetResp resp = client.get(getReq);return resp;}/*** 按照向量检索,找到相似度最近的topK*/public List<List<SearchResp.SearchResult>>  queryVector() {SearchResp searchR = client.search(SearchReq.builder().collectionName(COLLECTION_NAME).data(Collections.singletonList(new FloatVec(new float[]{0.9f, 2.1f}))).topK(3).outputFields(Collections.singletonList("*")).build());List<List<SearchResp.SearchResult>> searchResults = searchR.getSearchResults();for (List<SearchResp.SearchResult> results : searchResults) {for (SearchResp.SearchResult result : results) {log.info("ID="+(String)result.getId() + ",Score="+result.getScore() + ",Result="+result.getEntity().toString());}}return searchResults;}}

这里使用到的一个简单的pojo类

public class TestRecord {private String id;private String title;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}}

6、创建Controller

import com.yuncheng.milvus.service.MilvusDemoService;
import io.milvus.v2.service.vector.response.GetResp;
import io.milvus.v2.service.vector.response.SearchResp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.io.IOException;
import java.util.List;@RestController
@RequestMapping("/milvus")
public class MilvusController {private static final Logger log = LoggerFactory.getLogger(MilvusController.class);@Autowiredprivate MilvusDemoService milvusDemoService;@GetMapping("/createCollection")public void createCollection() {milvusDemoService.createCollection();}@GetMapping("/insertRecord")public void insertRecord() throws IOException {TestRecord record = new TestRecord();record.setId("5");record.setTitle("北京是中国的首都,人口有3000多万人");milvusDemoService.insertRecord(record);}@GetMapping("/getRecord")public GetResp getRecord(@RequestParam(name = "id") String id){GetResp resp = milvusDemoService.getRecord(id);log.info("resp = " +  resp.getResults);return resp;}@GetMapping("/queryVector")public List<List<SearchResp.SearchResult>> queryVector() {List<List<SearchResp.SearchResult>> searchResults = milvusDemoService.queryVector();return searchResults;}}

7、测试验证CRUD

确保milvus2.5.4向量数据库正常运行,然后启动springboot工程,进行对milvus向量数据库测试验证。

7.1、创建Collection

http://localhost:8080/milvus/createCollection

执行后,登录milvus控制台webUI查看

点击collection名称,查看详细的结构定义,类似于mysql中的表结构定义:

其中,id、title、title_vector字段是程序里定义的字段,另外RowID和Timestamp字段是collection默认自带的字段。

7.2、插入数据

http://localhost:8080/milvus/insertRecord

为了测试方便,本示例写死了测试数据,往milvus中插入了5条数据

7.3、查询单条记录

http://localhost:8080/milvus/getRecord?id=2

返回JSON结果集

{

  "getResults": [

    {

      "entity": {

        "title_vector": [1, 2],

        "id": "2",

        "title": "张三是英国人,他喜欢吃中国火锅"

      }

    }

  ]

}

7.4、按向量检索相似度

http://localhost:8080/milvus/queryVector

返回结果集:

[

  [

    {

      "entity": {

        "title_vector": [0.8, 1.9],

        "id": "4",

        "title": "王五是老师,她教学AI算法"

      },

      "score": 0.9999797,

      "id": "4"

    },

    {

      "entity": {

        "title_vector": [1, 2],

        "id": "2",

        "title": "张三是英国人,他喜欢吃中国火锅"

      },

      "score": 0.99827427,

      "id": "2"

    },

    {

      "entity": {

        "title_vector": [1, 2],

        "id": "1",

        "title": "我是中国人,我喜欢吃火锅"

      },

      "score": 0.99827427,

      "id": "1"

    }

  ]

]

其中,score为向量相似度分值,如果score=1,则表示完全一样,score小于1,表示接近。这里为了测试方面,插入数据时,在向量字段里写死了几个固定的List<Float>值,真实的业务场景中,要通过Embedding模型计算生成,后续文章中介绍如何调用AI中的Embedding服务,生成向量化的float值。


http://www.ppmy.cn/news/1571547.html

相关文章

ASP.NET Core DDD

目录 什么是微服务 单体结构项目 微服务架构项目 微服务架构误区 什么是DDD DDD领域与领域模型 领域&#xff08;Domain&#xff09; 领域模型&#xff08;Domain Model&#xff09; 事务脚本 事务脚本的问题 通用语言与界限上下文 通用语言 界限上下文 实体与值…

龙迅LT8711UXD 高性能2PORT TYPE-CDPEDP转HDMi 2.0加PD 3.0,内置MCU

龙迅LT8711UXD描述&#xff1a; LT8711UXD是一款高性能的双车道TypeC/DP1.4到HDMI2.0转换器&#xff0c;设计用于将USB Type-C源或DP1.4源连接到HDMI2.0接收器。LT8711UXD集成了一个DP1.4兼容的接收机&#xff0c;和一个HDMI2.0兼容的发射机。此外&#xff0c;还包括两个CC控制…

PDF翻译自动化:利用Make打造反思翻译工作流

PDF翻译自动化&#xff1a;利用Make打造反思翻译工作流 当今这个信息爆炸的时代&#xff0c;你是否曾觉得翻译工作就像一座高山&#xff0c;昂首而立&#xff1f;面对成堆的PDF文档&#xff0c;从提取内容到翻译、再到编辑校对&#xff0c;这一系列任务不仅耗时&#xff0c;还…

STM32 RTC亚秒

rtc时钟功能实现&#xff1a;rtc模块在stm32内部&#xff0c;由电池或者主电源供电。如下图&#xff0c;需注意实现时仅需设置一次初始化。 1、stm32cubemx 代码生成界面设置&#xff0c;仅需开启时钟源和激活日历功能。 2、生成的代码,需要对时钟进行初始化&#xff0c;仅需…

Python:凯撒密码

题目内容&#xff1a; 凯撒密码是古罗马恺撒大帝用来对军事情报进行加密的算法&#xff0c;它采用了替换方法对信息中的每一个英文字符循环替换为字母表序列该字符后面第三个字符&#xff0c;对应关系如下&#xff1a; 原文&#xff1a;A B C D E F G H I J K L M N O P Q R …

【Elasticsearch】监控与管理:集群监控指标

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

后台管理系统网页开发

CSS样式代码 /* 后台管理系统样式文件 */ #container{ width:100%; height:100%; /* background-color:antiquewhite;*/ display:flex;} /* 左侧导航区域:宽度300px*/ .left{ width:300px; height: 100%; background-color:#203453; display:flex; flex-direction:column; jus…

【C++】23.异常

文章目录 1. 异常的概念及使用1.1 异常的概念1.2 异常的抛出和捕获1.3 栈展开1.4 查找匹配的处理代码1.5 异常重新抛出1.6 异常安全问题1.7 异常规范 2. 标准库的异常 1. 异常的概念及使用 1.1 异常的概念 异常处理机制允许程序中独立开发的部分能够在运行时就出现的问题进行通…