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

本文主要是介绍SpringBoot集成Milvus实现数据增删改查功能,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《SpringBoot集成Milvus实现数据增删改查功能》milvus支持的语言比较多,支持python,Java,Go,node等开发语言,本文主要介绍如何使用Java语言,采用springboo...

Milvus是一款开源向量数据库,主要用于在大模型领域做向量查询的相关操作。milvus支持的语言比较多,支持python, Java, Go,node等开发语言。本文主要介绍如何使用Java语言,采用spri编程ngboot框架集成和调用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</artifacthttp://www.chinasem.cnId>
    <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.17
  port: 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;
    @Bean
    public MilvusClientV2 milvusClientV2() {
        String uri = "http://"+hosAvYhwZTHgUt+":"+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.serviphpce.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";
    //为了测试验证方便,向量维度定义2
    private 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 getTphpitle() {
        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);
    @Autowired
    private 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查看

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

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

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

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

7.2、插入数据

http://localhost:8080/milvus/insertRecord

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

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

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值。

到此这篇关于SpringBoot集成Milvus,实现数据增删改查的文章就介绍到这了,更多相关SpringBoot集成Milvus内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!

这篇关于SpringBoot集成Milvus实现数据增删改查功能的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1154260

相关文章

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.

Python中pywin32 常用窗口操作的实现

《Python中pywin32常用窗口操作的实现》本文主要介绍了Python中pywin32常用窗口操作的实现,pywin32主要的作用是供Python开发者快速调用WindowsAPI的一个... 目录获取窗口句柄获取最前端窗口句柄获取指定坐标处的窗口根据窗口的完整标题匹配获取句柄根据窗口的类别匹配获取句

Maven中引入 springboot 相关依赖的方式(最新推荐)

《Maven中引入springboot相关依赖的方式(最新推荐)》:本文主要介绍Maven中引入springboot相关依赖的方式(最新推荐),本文给大家介绍的非常详细,对大家的学习或工作具有... 目录Maven中引入 springboot 相关依赖的方式1. 不使用版本管理(不推荐)2、使用版本管理(推

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B

python处理带有时区的日期和时间数据

《python处理带有时区的日期和时间数据》这篇文章主要为大家详细介绍了如何在Python中使用pytz库处理时区信息,包括获取当前UTC时间,转换为特定时区等,有需要的小伙伴可以参考一下... 目录时区基本信息python datetime使用timezonepandas处理时区数据知识延展时区基本信息

Python位移操作和位运算的实现示例

《Python位移操作和位运算的实现示例》本文主要介绍了Python位移操作和位运算的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 位移操作1.1 左移操作 (<<)1.2 右移操作 (>>)注意事项:2. 位运算2.1

如何在 Spring Boot 中实现 FreeMarker 模板

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文... 目录什么是 FreeMarker 模板?在 Spring Boot 中实现 FreeMarker 模板1. 环

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义