前置文章JAVA25 Spring Boot 4.1.0 Spring AI 2.0.1 调用 DeepSeek 模型JAVA25 Spring Boot 4.1.0 Spring AI 2.0.1 加载本地 embeddings 模型 bge-m3前言向量数据库是一种特殊类型的数据库在人工智能应用中扮演着至关重要的角色。向量数据库的查询方式与传统关系型数据库有所不同它不进行精确匹配而是执行相似性搜索。当以向量作为查询条件时向量数据库会返回与查询向量“相似”的向量。关于相似度的具体计算方式请参阅“向量相似性”一节。向量数据库用于将数据与人工智能模型集成。使用向量数据库的第一步是把数据加载到向量数据库中随后当用户向人工智能模型发起查询时系统会先检索出一组相似的文档这些文档将作为用户问题的上下文与用户的查询一并发送给人工智能模型。这种技术被称为检索增强生成RAG。Spring AI 提供了大量接口支持多种向量数据库实现并附有若干进阶用法示例。详细信息可查阅官方文档Spring AI 官网 Vector DatabasesSpring AI 官网 Vector Databases Milvus本文在前置文章的基础上进一步扩展讲解如何在项目中使用 Spring AI 对接 Milvus 向量数据库。注意请务必先完成前置文章JAVA25 Spring Boot 4.1.0 Spring AI 2.0.1 加载本地 embeddings 模型 bge-m3中的配置否则项目启动时会报错。一、安装 Milvus 3.0.xMilvus 3.0.x 版本里面会更新了很多功能为了以后扩展建议安装 Milvus 3.0.x。Milvus 官网Milvus 官网安装页面安装 Milvuswgethttps://github.com/milvus-io/milvus/releases/download/v3.0.3/milvus-standalone-docker-compose.yaml-Odocker-compose.yamlsudodockercompose up-dCreating milvus-etcd...doneCreating milvus-minio...doneCreating milvus-standalone...done注意指令在哪个文件夹下运行会在当前目录创建数据文件创建的数据文件记得给权限否则docker 启动有可能报错。停止并删除 Milvussudodockercompose downsudorm-rfvolumes安装 Milvus 连接工具Attu 首页下载 Attu 页面二、Maven 引入!-- Milvus 向量存储 Spring AI 官方 Starter --dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-starter-vector-store-milvus/artifactId/dependency三、添加 application.yml 配置# Spring 配置spring:# Spring AI 配置 ai:# 向量库配置 vectorstore:# Milvus 向量库配置 milvus:client:# 连接 Milvus 向量库 IPhost:121.43.122.232# 连接 Milvus 向量库端口port:19530# username: root# password: Milvus#默认数据库名称databaseName:default#数据库中集合名称collectionName:vector_store#存入 Milvus 的向量Embedding的维度大小 务必与 向量化模型 输出维度一致embeddingDimension:1024# 索引类型 IVF_FLAT适合中等规模数据平衡查询速度和精度indexType:IVF_FLAT# 相似度度量类型 COSINE 余弦相似度常用于文本向量metricType:COSINE#是否要为你自动在 Milvus 中创建用于存储向量数据的集合Collection及其结构SchemainitializeSchema:true四、创建 DTO向量新增修改请求参数记录对象importio.swagger.v3.oas.annotations.media.Schema;importlombok.*;importlombok.experimental.Accessors;importorg.springframework.ai.document.Document;importjava.io.Serial;importjava.io.Serializable;importjava.util.List;/** * description: 向量新增修改请求参数记录对象 * author: LIHAO * createDate: 2026-11-02 17:13:49 */DataBuilder(toBuildertrue)WithNoArgsConstructorAllArgsConstructorAccessors(chaintrue)Schema(title向量新增修改请求参数对象)publicclassVectorUpsertRequestimplementsSerializable{SerialprivatestaticfinallongserialVersionUID1L;Schema(description存储名称用于标识使用的向量存储实例RedisVectorStore Bean名称主要作用获取集合名称如果传递collectionName参数以collectionName参数为主。没有传递以storeBeanName获取为主)privateStringstoreBeanName;Schema(description集合名称)privateStringcollectionName;Schema(description分区名称一个数据库中一个集合里面的不同分区名称)privateStringpartitionName;Schema(description拆分好的文档数据,requiredModeSchema.RequiredMode.REQUIRED)privateListDocumentdocumentList;}向量检索请求参数importio.swagger.v3.oas.annotations.media.Schema;importlombok.*;importlombok.experimental.Accessors;importjava.io.Serial;importjava.io.Serializable;importjava.util.List;/** * description: 向量检索请求参数 * author: LIHAO * createDate: 2026-11-02 17:13:58 */DataBuilder(toBuildertrue)WithNoArgsConstructorAllArgsConstructorAccessors(chaintrue)Schema(title向量检索请求参数对象)publicclassVectorQueryRequestimplementsSerializable{SerialprivatestaticfinallongserialVersionUID1L;Schema(description向量数据id)privateStringid;Schema(description向量数据id集合)privateListStringidList;Schema(description存储Bean名称用于标识使用的向量存储实例RedisVectorStore Bean名称)(主要作用获取集合名称如果传递collectionName参数以collectionName参数为主。没有传递以storeBeanName获取为主))privateStringstoreBeanName;Schema(description集合名称)privateStringcollectionName;Schema(description分区名称一个数据库中一个集合里面有不同分区名称)privateStringpartitionName;Schema(description检索文本,requiredModeSchema.RequiredMode.AUTO)privateStringtext;Schema(description返回结果数量可为空使用系统默认值通常为4)privateIntegertopK;Schema(description相似度阈值仅返回相似度高于此值的文档范围通常为0~1可为空系统默认值通常为0.0无阈值限制)privateFloatsimilarityThreshold;Schema(description是否重排序true重排序false不重排序)privateBooleanisReranker;Schema(description元数据过滤条件用于在检索时对文档元数据进行过滤如果添加向量时是章节拆分默认添加元数据字段fileName文件名称、chapters章、section节、subsection小节、detailedChapters章/节/小节语法示例metadata[country] UK metadata[year] 2020 metadata[isActive] true Or metadata[country] BG (metadata[city] NOT IN [Sofia, Plovdiv] || price 134.34))privateStringmetaDataWhere;Schema(description分词匹配词间隔位置允许匹配词之间最多间隔几个位置0代表必须相邻中间没有间隔位置。只限于短语匹配)privateIntegerslop;}五、创建向量库操作 Serviceimportcom.lh.vectorDatabases.milvus.dto.VectorQueryRequest;importcom.lh.vectorDatabases.milvus.dto.VectorUpsertRequest;importlombok.extern.slf4j.Slf4j;importorg.apache.commons.collections4.CollectionUtils;importorg.apache.commons.lang3.StringUtils;importorg.springframework.ai.document.Document;importorg.springframework.ai.vectorstore.SearchRequest;importorg.springframework.ai.vectorstore.VectorStore;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importorg.springframework.util.Assert;importjava.util.List;importjava.util.Map;/** * description: Milvus Store 向量操作 * author: LIHAO * createDate: 2026-11-02 15:05:58 */Slf4jService(milvusVectorStoreService)publicclassMilvusVectorStoreService{privateVectorStorevectorStore;publicMilvusVectorStoreService(VectorStorevectorStore){this.vectorStorevectorStore;}/** * description: 新增或修改向量数据 * author: LIHAO * createDate: 2026-11-02 17:16:58 * param: [storeBeanName RedisVectorStore Bean名称, documentList] * return: void */publicvoidupsert(VectorUpsertRequestvectorAddRequest){ListDocumentdocumentParamtListvectorAddRequest.getDocumentList();// 检查集合不为空Assert.notEmpty(documentParamtList,MilvusVectorStoreService#upsert参数vectorRequest#documentList不能为空);//新增或修改数据vectorStore.add(documentParamtList);}/** * description: 根据数据id据删除数据 * author: LIHAO * createDate: 2026-11-02 17:16:58 * param: [storeBeanName RedisVectorStore Bean名称, idList 数据id] * return: void */publicvoiddeleteById(VectorQueryRequestvectorRequest){ListStringidListvectorRequest.getIdList();// 检查集合不为空Assert.notEmpty(idList,MilvusVectorStoreService#deleteById参数vectorRequest#idList不能为空);if(CollectionUtils.isNotEmpty(idList)){//删除数据vectorStore.delete(idList);}}/** * description: 根据文本查询相关向量数据如语义搜索 * author: LIHAO * createDate: 2026-11-02 17:16:58 * param: [vectorRequest] * return: java.util.Listorg.springframework.ai.document.Document */publicListDocumentsearchByVector(VectorQueryRequestvectorRequest){//搜索内容StringtextvectorRequest.getText();//检查字符串不为空不是 null且长度 0Assert.hasLength(text,MilvusVectorStoreService#searchByVector,参数vectorRequest#text不能为空);// 构建 SearchRequest先设置固定参数SearchRequest.BuilderbuilderSearchRequest.builder().query(vectorRequest.getText());// 查询文本//获取搜索结果数量IntegertopKvectorRequest.getTopK();// 仅当 topK 不为 null 时才设置 topK否则使用系统默认值4由 RedisVectorStore 决定if(topK!nulltopK0){builder.topK(topK);}//获取相似度阈值仅返回相似度高于此值的文档范围通常为0~1可为空系统默认值通常为0.0无阈值限制FloatsimilarityThresholdvectorRequest.getSimilarityThreshold();// similarityThreshold 不为 null 时才设置 similarityThreshold否则使用系统默认值0.0由 RedisVectorStore 决定if(similarityThreshold!nullsimilarityThreshold0.0similarityThreshold1.0){builder.similarityThreshold(similarityThreshold);// 相似度阈值若为 nullbuilder 可能使用默认值}//元数据过滤条件用于在检索时对文档元数据进行过滤StringmetaDataWherevectorRequest.getMetaDataWhere();// 判断是否有元数据过滤if(StringUtils.isNotBlank(metaDataWhere)){builder.filterExpression(metaDataWhere);// 元数据过滤条件 metaDataWhere}// 生成最终的 SearchRequest 对象SearchRequestsearchRequestbuilder.build();//查询向量数据ListDocumentresultsvectorStore.similaritySearch(searchRequest);returnresults;}}六、测试用例Maven 引入!-- Milvus 向量存储 Spring AI 官方 Starter --dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-starter-vector-store-milvus/artifactId/dependencyjava代码importcom.lh.vectorDatabases.milvus.dto.VectorQueryRequest;importcom.lh.vectorDatabases.milvus.dto.VectorUpsertRequest;importcom.lh.vectorDatabases.milvus.service.MilvusVectorStoreService;importlombok.extern.slf4j.Slf4j;importorg.apache.commons.collections4.CollectionUtils;importorg.junit.jupiter.api.Test;importorg.springframework.ai.document.Document;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importjava.util.List;importjava.util.Map;Slf4jSpringBootTestpublicclassOriginApplicationTest{AutowiredprivateMilvusVectorStoreServicemilvusVectorStoreService;TestpublicvoidmilvusVectorStoreTest(){ListDocumentdocumentsList.of(newDocument(今天天气很好,Map.of(meta1,meta1)),newDocument(世界很大救赎就在拐角处),newDocument(你面对过去向前走然后转身面向未来。,Map.of(meta2,meta2)));//新增数据milvusVectorStoreService.upsert(VectorUpsertRequest.builder().documentList(documents).build());//查询数据ListDocumentresultsmilvusVectorStoreService.searchByVector(VectorQueryRequest.builder().text(今天).topK(20).build());System.out.println(results);if(CollectionUtils.isNotEmpty(results)){ListStringidListresults.stream().map(Document::getId).toList();//根据id删除数据milvusVectorStoreService.deleteById(VectorQueryRequest.builder().idList(idList).build());}}}七、总结本文围绕 Spring AI 对接 Milvus 向量数据库完整走通了从环境搭建到代码落地的全流程主要包含以下几个环节环境准备通过 Docker Compose 安装 Milvus 3.0.x并使用 Attu 作为可视化管理工具方便查看集合与向量数据。依赖与配置引入spring-ai-starter-vector-store-milvus官方 Starter在application.yml中完成连接地址、集合名称、向量维度、索引类型与相似度度量等关键参数配置。请求对象封装通过VectorUpsertRequest与VectorQueryRequest统一承载新增、删除、检索所需的参数便于后续扩展与复用。服务层实现MilvusVectorStoreService基于 Spring AI 的VectorStore抽象实现了向量新增/修改、按 ID 删除以及基于文本的相似性检索并对入参做了必要的校验。测试验证通过单元测试完成「写入 → 检索 → 删除」的闭环验证确认配置与代码均可正常工作。需要特别注意的几点embeddingDimension必须与所用向量化模型如 bge-m3的输出维度保持一致否则写入时会报维度不匹配错误。initializeSchema: true可让 Spring AI 自动创建集合与 Schema生产环境建议改为手动管理避免误建或结构变更。检索时topK、similarityThreshold等参数可按业务场景灵活调整配合metaDataWhere元数据过滤能显著提升召回质量。至此Spring AI Milvus 的基础集成已经完成。后续可以在此基础上继续扩展接入 RAG 问答链路、结合重排序模型优化召回结果或将向量检索能力封装为统一的内部服务供多个业务模块调用。
阅读完成 · 觉得有帮助?