向量数据库Elasticsearch(一)

目录

一.什么是向量数据库

二.Elasticsearch数据库初识

三.Elasticsearch数据库安装

四.Elasticsearch数据库增加数据与索引&KNN查询数据


一.什么是向量数据库

向量数据库 是一种专门用于存储、索引和检索高维向量数据的数据库系统。与传统关系型数据库不同,向量数据库的核心能力是相似 度搜索 ,即根据向量之间的相似度快速找到最相似的数据。
核心概念

  • 向量(Vector:由多个数值组成的数组,通常用于表示文本、图像、音频等非结构化数据的语义特征。
  • 嵌入(Embedding:将非结构化数据转换为向量的过程,通过大模型的Embedding模型实现。
  • 相似度计算:通过余弦相似度、欧氏距离、点积等方法衡量向量之间的相似程度。
  • 近似最近邻搜索(ANN:在百万甚至亿级向量中快速找到最相似的Top-K结果。

数据在数据库中以向量的形式存储,检索时,也先将检索的关键字转化为向量,再去数据库里检索,这语义的概念学过深度学习的人很好理解。
应用场景

  • RAG系统中的文档检索
  • 推荐系统中的相似物品查找
  • 图像搜索与识别
  • 语义搜索
  • 异常检测

为什么需要向量数据库
传统数据库的局限性

  • 关系型数据库无法高效处理高维向量数据
  • 精确匹配无法满足语义相似度搜索需求
  • 传统索引结构(B+树、哈希表)不适合向量检索

向量数据库的优势
高效相似度搜索 :通过专门的索引算法( HNSW 、 IVF 等)实现毫秒级检索
大规模支持 :可处理百万到亿级向量数据
语义理解 :支持基于语义而非关键词的检索
多模态支持 :可处理文本、图像、音频等多种数据类型
谁在使用向量数据库?
典型用户群体
AI 应用开发者 :构建 RAG 系统、智能问答、推荐系统
数据科学家 :进行相似度分析、聚类、异常检测
企业技术团队 :构建企业知识库、文档检索系统
产品经理 :需要语义搜索、个性化推荐等功能的业务场景

如何使用 向量数据库
基本工作流程

  • 数据准备:将原始数据(文档、图片等)通过Embedding模型转换为向量
  • 向量存储:将向量数据导入向量数据库并建立索引
  • 查询处理:将用户查询转换为向量,在数据库中搜索相似向量
  • 结果返回:返回最相似的Top-K结果及其原始数据
    选型关键因素
    性能 :查询速度、吞吐量、延迟
    成本 :开源免费 vs 云服务付费、硬件资源需求
    易用性 : API 友好度、部署复杂度、文档完善度
    扩展性 :单机 vs 分布式、水平扩展能力
    功能特性 :是否支持混合检索、元数据过滤、实时更新

主流向量数据库产品概览

  • FAISS:Facebook开源,本地部署,适合研究和小规模应用
  • Milvus:开源分布式,企业级,适合大规模生产环境
  • Elasticsearch:支持向量检索+全文检索混合,企业级首选
  • Pinecone:云服务,开箱即用,适合快速原型
  • Chroma:轻量级,易部署,适合中小型项目
  • Qdrant:高性能,Rust实现,适合对性能要求高的场景
  • Weaviate:图数据库+向量检索,适合复杂关系场景

向量数据库的本质 :专门用于高维向量相似度搜索的数据库系统,是RAG 系统的核心基础设施。
选型三要素

  • 性能
    吞吐量: QPS,每秒请求数,系统能扛多大并发压力
    延迟: P99, 99% 的用户在指定毫秒内看到结果,响应速度
    召回率: Recall@K, 相关结果被找出来的比例

  • 成本:开源 vs 云服务、资源消耗(单位 QPS 或每百万向量的资源消耗(CPU/GPU/内存))

  • 易用性:部署复杂度、API友好度、团队熟悉度
    主流产品定位

  • FAISS:研究开发、小规模、本地部署

  • Milvus:企业级、大规模、分布式

  • Elasticsearch:混合检索、企业级、统一平台 ⭐⭐

  • Pinecone:快速原型、云服务、零运维

  • Chroma/Qdrant/Weaviate:轻量级、特定场景、快速集成

数据库的选择
场景 1 :个人学习 / 小项目
推荐 : FAISS 或 Chroma
理由:免费、简单、资源消耗低
场景 2 :企业生产环境(大规模)
推荐 : Milvus 或 Elasticsearch
理由:稳定性、扩展性、企业级功能
场景 3 :快速原型 / 无运维
推荐 : Pinecone
理由:开箱即用、零运维
场景 4 :混合检索需求
推荐 : Elasticsearch
理由:全文检索 + 向量检索统一平台
场景 5 :性能极致要求
推荐 : Qdrant 或 FAISS ( GPU )
理由:性能优秀、延迟低

二.Elasticsearch数据库初识

Elasticsearch ES 是一个分布式搜索与分析引擎。自 7.3 版本 , ES 原生支持 kNN (近邻)向量检索 ,实现了 全文检索向量 语义检索 的统一,为混合搜索场景提供了强大支持。

为什么选择 Elasticsearch
适用场景

  • 混合检索需求:需同时支持关键词匹配与语义相似度搜索。
  • 已有ES基础设施:团队已熟悉 ES,可快速集成向量能力,降低迁移与学习成本。
  • 企业级系统要求:需要成熟的监控、日志管理、安全控制和高可用架构。
  • 多维复杂查询:需结合结构化字段、地理位置、时间范围与向量进行联合查询。

核心优势
统一平台 :全文检索 + 向量检索一体化,避免多系统维护。
企业就绪 :内置安全、监控、告警、可视化( Kibana )等运维能力。
灵活查询 DSL :支持复杂组合查询、过滤、聚合与排序。
横向扩展 :支持 PB 级数据规模,具备良好的集群伸缩性。

局限性
⚠️ 性能 vs 专用向量库 :在纯向量检索场景下,吞吐与延迟略逊于 FAISS 、 Milvus 等专业向量数据库。
⚠️ 资源开销较大 :向量索引会显著增加内存与存储消耗。
⚠️ 配置复杂度高 :需合理调优分片、索引策略及硬件资源配置。

谁适合使用 Elasticsearch 的向量检索?

  • 已有 Elasticsearch 技术栈的团队
  • 需要 关键词**+**语义混合搜索的产品(如智能客服、商品推荐、内容搜索
  • 系统可观测性、安全性、稳定性有较高要求的企业用户
  • 业务涉及 多条件联合检索(如"价格 < 100 元 + 地理位置附近 + 语义相关")

性能表现


kNN 搜索类型对比

提示

  • script_score 是 Elasticsearch 查询DSLDomain Specific Language)中的一种自****定义打分机制。它允许通过编写 Painless****脚本(Elasticsearch 的安全脚本语言)来动态计算每个文档的相关性得分( _score )
  • knn 查询是"新标准":利用向量索引实现高效近似搜索,快且易用,是生产首选。
  • Elasticsearch 默认使用 HNSW**(Hierarchical Navigable Small World)**算法构建近似向量索引。

最佳实践
优先使用近似 kNN knn 查询) ,避免 script_score 全量计算。
合理设计分片数量 :过多分片增加协调开销,过少影响并行能力。
采用 RRF 融合策略 ,平衡关键词与语义信号,提升整体相关性。
定期优化索引 :合并段( force merge )、清理冷数据、监控 JVM 与磁盘使用。
控制向量维度 :高维向量( >1024 )显著增加内存与计算负担,建议降维或裁剪。

提示
Elasticsearch 8.0 ,向量字段类型为 dense_vector ,并持续增强对混合搜索、过滤向量检索(filtered kNN )的支持。建议使用 8.8+ 版本 以获得最佳功能与性能体验。

三.Elasticsearch数据库安装

官网: https://www.elastic.co/cn/elasticsearch
方法 1 :使用 Docker (最简单,推荐开发测试)
方法 2 :本地安装( Linux/macOS/Windows
官网下载: Download Elasticsearch | Elastic (可以选择下载压缩包本地安装 or 通过Docker使用)
解压并启动


本文使用Docker的方式来安装,对于企业来说,会选择安装多节点的版本,但对于学习者来说,单节点足矣,
在docker hub上搜索elastic ,然后找到elasticsearch,然后可以选择到相关的版本,执行相关命令,
下载docker desktop,检查电脑是否安装WSL(科学上网安装起来比较快),新版要求有WSL,要不然用不了,

拉取官方镜像(以 9.4.6 为例)

docker pull elastic/elasticsearch:9.4.6

启动容器(单节点,关闭安全认证便于测试)第一个-p代表的是HTTP端口号,第二个-p代表的是多节点之间通信的端口号,如果是单节点的话,就把第二个-p和端口号删除,最后的东西是你拉下来的镜像的名称

docker run -d --name es-knn -p 9200:9200 -p 9300:9300 -e discovery.type=single-node -e xpack.security.enabled=false elastic/elasticsearch:9.4.6

执行之后,docker desktop会出现相应的容器,找到es的那个容器,点击按钮启动
Python 的使用
安装与连接

安装 Elasticsearch 客户端

pip install elasticsearch

四.Elasticsearch数据库增加数据与索引&KNN查询数据

完整代码示例
elasticsearch的参考文档在官网Docs的 Reference里。也去可以去pypi网站上查找相关参考文档(搜索elasticsearch)

python 复制代码
from elasticsearch import Elasticsearch
import numpy as np

# 准备数据
items = [
    {"type": "phone", "id": "用户A", "number": 13800001234},
    {"type": "phone", "id": "用户B", "number": 13800005678},
    {"type": "order", "id": "订单1001", "number": 203011010001},
    {"type": "order", "id": "订单1002", "number": 203011010123},
    {"type": "order", "id": "订单2001", "number": 203012150045},
    {"type": "phone", "id": "用户C", "number": 13912345678},
    {"type": "phone", "id": "用户D", "number": 13798765432},
    {"type": "order", "id": "订单3001", "number": 205001020333},
    {"type": "order", "id": "订单3002", "number": 205001020777},
    {"type": "phone", "id": "用户E", "number": 13622223333},
]

# 链接ES
from numpy import indices

es = Elasticsearch(
    # scheme="http",为设置链接协议为http协议
    hosts = [{'host':'localhost','port':9200,'scheme':'http'}],
    #超过30秒没有响应就会触发超时异常
    request_timeout = 30 # 默认0秒会触发超时
)

# 创建索引参数
index_name = 'number_vector'
mapping = {
    #mappings为索引的映射配置,定义了索引的字段和字段的类型
    #mappings和properties是固定的,再里面的才是自己写的
    "mappings": {
        "properties": {
            # 四个属性,其中一个是索引,另外三个为普通属性
            "number_vector": {
                "type": "dense_vector",# 密集向量类型
                "dims": 1, #维度为1
                "index": True, #是否为索引
                "similarity": "l2_norm"  # L2欧式距离
            },
            "type":{"type":"keyword"}, #es只有keyword和text两种字符串类型,keyword是精确匹配,text是分词匹配
            "id":{"type":"keyword"},
           "number":{"type":"long"} #长整型
        }
    }
}

# 删除已存在的索引
if es.indices.exists(index=index_name):  # 索引存在
    es.indices.delete(index=index_name)

# 创建索引
try:
    #新写法
    es.indices.create(index=index_name, mappings=mapping['mappings'])
except TypeError:
    #马上淘汰的旧写法,不建议使用
    es.indices.create(index=index_name, body=mapping)

# 构建数据插入数据库
dimension = 1

for i ,item in enumerate(items):
    # 把number字段转换为浮点数,并放入一个列表中,作为索引字段(有大模型时可以转化为语义向量再当作索引字段)
    number_vector = [float(item['number'])]
    # 在索引中创建或更新数据
    es.index(
        index = index_name,
        id = i+1,
        document= {
            # 索引
            "number_vector": number_vector,
            #下面皆为属性字段
            "type": item['type'],
            "id": item['id'],
            "number": item['number']
        }
    )
print(f'已向索引添加 {len(items)} 个数字向量 (维度={dimension})')
# 刷新索引
es.indices.refresh(index=index_name)

query_number = 205001020500
#转换成和数据库里存储同样的形式
query_vector = [float(query_number)]

k = 5 # 搜索最接近的5个向量

knn_query ={
    'size':k,
    '_source':['type','id','number','number_vector'], #搜索结果返回的字段
    # knn参数
    'knn':{
        # 根据number_vector字段进行knn查询
        'field':'number_vector',
        # 查询向量
        'query_vector':query_vector,
        'k':k,
        'num_candidates':100  # 粗排阶段候选向量数量(100个),然后再从100个中选出5个,越大精度消耗的资源越多
    }
}

results = es.search(index=index_name,body=knn_query)

print("\n查询数字:", query_number)
print(f"Top-{k} 最相近数字(按 L2 距离,越小越相近):")

print(results)

for rank, hit in enumerate(results["hits"]["hits"], start=1):
    source = hit['_source']
    print(f"{rank}. 得分={hit['_score']:.4f} | 类型={source['type']} | 标识={source['id']} | 数字={source['number']}")
相关推荐
residual_fan35 分钟前
持续对比强化学习(Continual Contrastive Reinforcement Learning)论文分享
人工智能·算法·数据挖掘·数据分析
深维AI随笔38 分钟前
《构建之法》| 第六章敏捷流程:敏捷不是“快“,而是“响应变化“,AI时代怎么敏捷
人工智能·敏捷流程·构建之法
Raas10041 分钟前
AI网关和LLM网关区别?MAI Gateway(魔芋企业级AI网关)企业级方案对比指南
大数据·人工智能·gateway·mai gateway·企业级产品
imbackneverdie44 分钟前
国内有哪些比较全面的生物医学相关数据库?
大数据·数据库·人工智能·ai·信息可视化·aigc·科研
心易行者1 小时前
Python自动化测试7步落地法:用python在线运行省掉90%环境配置时间
java·开发语言·人工智能·python·log4j·ai编程
茗鹤APS和MES1 小时前
工业排产:AI可赋能,APS不可替代
人工智能·深度学习·机器学习
东离与糖宝1 小时前
深度拆解Claude Code架构:不靠总管,靠边界搭建编程Agent
人工智能
Sophnet云平台1 小时前
从 IT 自嗨到业务可用,制造企业 AI 平台的落地实践
大数据·人工智能·llm·制造·token·云平台
ting94520001 小时前
Hey Noah 主动式 AI 执行助理全栈技术深度剖析 —— 从被动对话 LLM 到 FSD 级自主 Agent 工程实现
人工智能·架构