使用原生ES当向量数据库
1. Maven 依赖 (pom.xml)xmldependencies !-- Spring Boot Web -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Elasticsearch 8.x 官方 Java Client -- dependency groupIdco.elastic.clients/groupId artifactIdelasticsearch-java/artifactId version8.12.0/version /dependency !-- ES Client 底层通信依赖 -- dependency groupIdorg.elasticsearch.client/groupId artifactIdelasticsearch-rest-client/artifactId version8.12.0/version /dependency !-- Jackson JSON 处理 -- dependency groupIdcom.fasterxml.jackson.core/groupId artifactIdjackson-databind/artifactId version2.15.2/version /dependency /dependencies2. 模拟 Embedding 模型服务 (EmbeddingService.java)在实际业务中这里会替换为调用 OpenAI、通义千问等真实 API 的代码。这里为了演示我们生成一个固定维度的随机向量。javaimport org.springframework.stereotype.Service; import java.util.Random; Service public class EmbeddingService { private static final int VECTOR_DIM 768; // 假设模型输出 768 维 private final Random random new Random(); /** * 将文本转换为向量 * 【实际业务中在此处通过 HTTP 调用大模型 Embedding API】 */ public float[] embed(String text) { // 模拟生成 768 维的随机向量 float[] vector new float[VECTOR_DIM]; for (int i 0; i VECTOR_DIM; i) { vector[i] random.nextFloat(); } return vector; } }3. ES 客户端配置 (ElasticsearchConfig.java)javaimport co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.json.jackson.JacksonJsonpMapper; import co.elastic.clients.transport.ElasticsearchTransport; import co.elastic.clients.transport.rest_client.RestClientTransport; import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class ElasticsearchConfig { Bean public RestClient restClient() { return RestClient.builder(new HttpHost(localhost, 9200, http)).build(); } Bean public ElasticsearchClient elasticsearchClient(RestClient restClient) { ElasticsearchTransport transport new RestClientTransport(restClient, new JacksonJsonpMapper()); return new ElasticsearchClient(transport); } }4. 核心业务 Controller (VectorController.java)这个 Controller 包含了创建索引、写入文档自动调用 Embedding、以及 kNN 检索的完整流程。javaimport co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch.core.SearchResponse; import co.elastic.clients.elasticsearch.core.search.Hit; import org.springframework.web.bind.annotation.*; import java.util.*; RestController RequestMapping(/api/vector) public class VectorController { private final ElasticsearchClient esClient; private final EmbeddingService embeddingService; private static final String INDEX_NAME my_native_vector_index; private static final int VECTOR_DIM 768; public VectorController(ElasticsearchClient esClient, EmbeddingService embeddingService) { this.esClient esClient; this.embeddingService embeddingService; } /** * 1. 初始化索引 (只需调用一次) */ PostMapping(/init-index) public String initIndex() throws Exception { boolean exists esClient.indices().exists(e - e.index(INDEX_NAME)).value(); if (exists) return 索引已存在无需重复创建; esClient.indices().create(c - c .index(INDEX_NAME) .mappings(m - m .properties(content, p - p.text(t - t)) .properties(content_vector, p - p.denseVector(dv - dv .dims(VECTOR_DIM) .index(true) .similarity(cosine) )) ) ); return 索引创建成功; } /** * 2. 写入文档 (核心在这里调用 Embedding 模型并将向量放入文档) */ PostMapping(/add) public String addDocument(RequestBody MapString, String payload) throws Exception { String content payload.get(content); // 【关键步骤】调用模型生成向量 float[] vector embeddingService.embed(content); // 组装文档必须包含 content_vector 字段 MapString, Object doc new HashMap(); doc.put(content, content); doc.put(content_vector, vector); // 将生成的向量塞入文档 // 写入 ES esClient.index(i - i.index(INDEX_NAME).document(doc)); return 文档向量化并存储成功; } /** * 3. kNN 向量检索 */ GetMapping(/search) public ListMapString, Object search(RequestParam String query, RequestParam(defaultValue 5) int topK) throws Exception { // 【关键步骤】查询文本也需要调用模型生成向量 float[] queryVector embeddingService.embed(query); SearchResponseMap response esClient.search(s - s .index(INDEX_NAME) .knn(k - k .field(content_vector) .queryVector(queryVector) .k(topK) .numCandidates(topK * 10) ), Map.class ); // 格式化返回结果 ListMapString, Object results new ArrayList(); for (HitMap hit : response.hits().hits()) { MapString, Object map new HashMap(); map.put(score, hit.score()); map.put(content, hit.source().get(content)); results.add(map); } return results; } }ES索引示例PUT /vector_docs { settings: { number_of_shards: 3, number_of_replicas: 1, index.knn: true, // 必须开启KNN插件总开关 index.knn.algo_param.ef_search: 100 }, mappings: { properties: { content: { type: text }, // 原始文本全文检索 doc_id: { type: keyword }, embedding: { type: dense_vector, dims: 1536, index: true, index_options: { type: hnsw }, similarity: cosine } } } }注意这里dims要和embedding模型维度一致维度由embedding决定(特例:动态embedding可以指定维度) 核心实现逻辑总结解耦设计ES 客户端只负责“存”和“搜”不负责“文本转向量”。写入流程在addDocument接口中先调用embeddingService.embed(content)拿到float[]然后doc.put(content_vector, vector)最后交给 ES 存储。检索流程在search接口中用户的查询语句query也必须先经过embeddingService.embed(query)变成向量才能传给 ES 的.queryVector(queryVector)进行比对。

相关新闻

Verilog硬件描述语言入门:从编程思维到硬件电路设计

Verilog硬件描述语言入门:从编程思维到硬件电路设计

1. 从“连线”到“描述”:为什么Verilog不是编程语言如果你是从单片机或者软件编程转过来的,第一次接触Verilog,最大的误区可能就是把它当成C语言或者Python来学。我见过不少新手,一上来就琢磨“这个for循环怎么写”、“这个函数怎…

2026/10/9 0:25:23 阅读更多 →
Jetson Nano从零配置指南:PyTorch、TensorFlow环境搭建与性能优化

Jetson Nano从零配置指南:PyTorch、TensorFlow环境搭建与性能优化

1. 项目概述:为什么需要一份“从零开始”的配置指南?如果你刚拿到一块Jetson Nano开发板,或者因为系统混乱、环境崩溃而不得不重装,那么恭喜你,你正处在一个最需要清晰指引的十字路口。Jetson Nano作为一款强大的边缘A…

2026/10/7 7:34:58 阅读更多 →
Android DownloadManager 核心机制与实战指南:从原理到避坑

Android DownloadManager 核心机制与实战指南:从原理到避坑

1. 项目概述:为什么我们需要DownloadManager?在Android应用开发中,文件下载是一个高频且基础的需求。无论是新闻应用缓存图片、音乐应用下载歌曲,还是电商应用保存商品详情,都离不开下载功能。很多开发者,尤…

2026/10/8 16:15:07 阅读更多 →

最新新闻

Java后端接入SignalR:从HTTP到HTTPS的完整落地与避坑指南

Java后端接入SignalR:从HTTP到HTTPS的完整落地与避坑指南

简介:面向Java与Android开发者的SignalR实时通信客户端库源码包,用于在非浏览器环境中接入ASP.NET SignalR服务,实现服务器向客户端实时推送。ASP.NET SignalR是一套成熟的实时Web通信库,而这份Java客户端扩展了它的使用边界&…

2026/10/11 20:38:24 阅读更多 →
Hermes自动化测试技能(1):用Jest/Pytest/Mocha搭建可复用的测试骨架

Hermes自动化测试技能(1):用Jest/Pytest/Mocha搭建可复用的测试骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 20:38:24 阅读更多 →
AMD Pensando vs BlueField-3:DPU实测性能差距与选型指南

AMD Pensando vs BlueField-3:DPU实测性能差距与选型指南

1. 从一颗DPU的实测数据说起第一次在实验室拿到AMD Pensando和BlueField-3这两块DPU做对比测试的时候,我心里其实是有预期的——Pensando被AMD收编之后,大家都等着看它到底能拿出什么成绩。结果跑完一轮基准测试,Pensando在特定负载下比BlueF…

2026/10/11 20:38:24 阅读更多 →
2026年十大AI Agent框架深度评测:TaoToken统一Key下谁是真正的王者

2026年十大AI Agent框架深度评测:TaoToken统一Key下谁是真正的王者

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 20:38:24 阅读更多 →
什么是IT资产自动发现?让CMDB和资产台账不再靠人工维护

什么是IT资产自动发现?让CMDB和资产台账不再靠人工维护

IT资产自动发现(Asset Discovery)是指通过扫描网络、读取设备信息等方式,自动识别企业环境中有哪些设备和软件、它们的配置是什么,并把结果同步到资产库的技术手段。 它解决的是 IT资产管理 里最老的一个难题:台账靠人…

2026/10/11 20:38:24 阅读更多 →
泥石流滑坡目标检测数据集:YOLO+VOC双格式解析与YOLOv8训练避坑指南

泥石流滑坡目标检测数据集:YOLO+VOC双格式解析与YOLOv8训练避坑指南

简介:目标检测数据集聚焦泥石流与滑坡两类地质灾害场景,面向需要训练YOLO、Faster R-CNN等检测模型的算法工程师、研究生及防灾减灾研究人员。数据集以VOC与YOLO双格式组织,JPEGImages、Annotations、labels三个文件夹一一对应,共…

2026/10/11 20:37:23 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →