当前位置: 首页 > news >正文

《Elasticsearch全文检索核心技术解析》

引言:为什么选择 ?

在当今数据爆炸的时代,我们每天都在与海量信息打交道。当你在电商平台搜索商品、在新闻网站筛选内容、在日志系统排查问题时,是否想过背后是什么技术支撑着这些快速而精准的搜索体验答案很可能是 Elasticsearch

Elasticsearch(简称 ES)是一个基于 Lucene 的分布式全文搜索引擎,它不仅能实现毫秒级的全文检索,还支持复杂的数据分析和聚合操作。作为 ELK 技术栈(Elasticsearch, Logstash, Kibana)的核心,它已成为企业级搜索、日志分析、实时监控等场景的首选解决方案。

一、Elasticsearch 核心概念解析

1.1 索引 (Index)

索引是 Elasticsearch 中存储数据的基本单元,类似于关系数据库中的表。但与表不同的是,索引是一个逻辑概念,它在物理上可能分布在多个节点上。

每个索引都有一个名称(必须全部小写),通过这个名称我们可以对索引中的文档进行 CRUD 操作。一个集群中可以有多个索引,例如我们可以有 "products" 索引存储商品数据,"users" 索引存储用户信息。

1.2 文档 (Document)

文档是 Elasticsearch 中最小的数据单元,类似于关系数据库中的行。每个文档都是一个 JSON 格式的字符串,包含了一个或多个字段。

每个文档都有一个唯一的 ID,可以由用户指定或由 Elasticsearch 自动生成。文档的结构灵活,不需要每个文档都有相同的字段,这为处理半结构化数据提供了便利。

1.3 字段 (Field)

字段是文档中的基本数据单元,类似于关系数据库中的列。每个字段都有其对应的数据类型,如字符串、数字、日期等。

Elasticsearch 会对字段进行索引,以便快速查询。对于字符串类型的字段,我们还可以指定分词器,控制如何将文本拆分为词条。

1.4 映射 (Mapping)

映射定义了索引中文档的结构,包括字段名称、数据类型、分词器等信息,类似于关系数据库中的表结构。

在 Elasticsearch 7.x 之后,已经移除了类型 (Type) 的概念,一个索引中只能有一个映射类型。映射可以显式定义,也可以由 Elasticsearch 根据插入的文档自动推断。

1.5 分片 (Shard)

为了处理海量数据,Elasticsearch 将一个索引的数据分成多个分片进行存储。每个分片是一个独立的 Lucene 索引,可以在集群中的不同节点上分布存储。

分片分为主分片 (Primary Shard) 和副本分片 (Replica Shard)。主分片负责数据的写入,副本分片是主分片的拷贝,用于提高查询性能和数据可用性。

索引创建时指定的主分片数量是固定的,而副本分片的数量可以随时调整。

二、Elasticsearch 的工作原理

2.1 倒排索引(全文检索的核心)

Elasticsearch 之所以能实现高效的全文检索,核心在于其采用了倒排索引 (Inverted Index) 的数据结构。

倒排索引与传统数据库的正向索引不同,它不是通过文档 ID 来查找内容,而是通过内容中的词条来定位包含该词条的文档

eg,假设我们有以下文档:

  1. 文档 1:"Elasticsearch 是一个搜索引擎"
  2. 文档 2:"Elasticsearch 基于 Lucene"
  3. 文档 3:"Lucene 是一个 Java 库"

倒排索引会先对这些文档进行分词,然后建立词条到文档的映射:

  • Elasticsearch: [1, 2]
  • 搜索引擎: [1]
  • 基于: [2]
  • Lucene: [2, 3]
  • Java: [3]
  • 库: [3]

当用户搜索 "Elasticsearch Lucene" 时,Elasticsearch 会找到包含这两个词条的文档交集,也就是文档 2,从而快速返回结果。

2.2 分布式架构

Elasticsearch 设计为分布式系统,这使其能够处理海量数据并提供高可用性

  1. 集群 (Cluster): 由一个或多个节点组成,共同存储整个数据集

  2. 节点 (Node): 单个 Elasticsearch 实例,每个节点都有一个唯一的名称。

  3. 分片 (Shard): 如前所述,将索引数据拆分存储,提高处理能力。

  4. 副本 (Replica): 分片的拷贝,提供冗余和高可用性,同时分担查询压力。

Elasticsearch 的分布式特性是自动管理的,用户无需手动干预数据在节点间的分布和迁移。当节点加入或离开集群时,Elasticsearch 会自动重新平衡数据。

三、环境搭建与基础配置

3.1 安装 Elasticsearch

在 Windows 环境下安装 Elasticsearch 非常简单:

  1. 从官网 (https://www.elastic.co/cn/downloads/elasticsearch) 下载最新版本的 Elasticsearch。
  2. 解压到本地目录,例如D:\elasticsearch-8.6.0。
  3. 进入bin目录,双击elasticsearch.bat启动服务。
  4. 打开浏览器访问http://localhost:9200,如果看到类似以下的 JSON 响应,说明安装成功
{"name" : "DESKTOP-XXX","cluster_name" : "elasticsearch","cluster_uuid" : "XXXXXXXXXXXXXXXXXXXX","version" : {"number" : "8.6.0","build_flavor" : "default","build_type" : "zip","build_hash" : "XXXXXXX","build_date" : "2023-01-04TXXXX","build_snapshot" : false,"lucene_version" : "9.4.2","minimum_wire_compatibility_version" : "7.17.0","minimum_index_compatibility_version" : "7.0.0"},"tagline" : "You Know, for Search"
}

 3.2IK分词器

分词器的作用是什么?

创建倒排索引时对文档分词 用户搜索时,对输入的内容分词

IK分词器有几种模式?

  • ik_smart:智能切分,粗粒度 
  • ik_max_word:最细切分,细粒度

安装 下载

  • https://github.com/medcl/elasticsearch-analysis-ik/releases
  • 在ES安装目录下找到plugins目录创建ik文件夹
  • ik分词器解压缩在此目录并重启ES即可

、索引与文档 

4.1 创建索引

PUT /hotel
{"mappings": {"properties": {"id": { "type": "keyword" },"name": { "type": "text", "analyzer": "ik_max_word","copy_to": "all"},"address": { "type": "keyword", "index": false },"price": { "type": "integer" },"brand": { "type": "keyword","copy_to": "all"},"city": { "type": "keyword","copy_to": "all"},"location": { "type": "geo_point" },"all": { "type": "text", "analyzer": "ik_max_word"}}}
}

在这个映射中:

  • id使用keyword类型,适合精确匹配
  • name使用text类型,并指定 IK 分词器
  • address设置index: false,表示不参与搜索
  • copy_to属性将多个字段的值复制到all字段,方便进行多字段联合搜索
  • location使用geo_point类型,支持地理坐标相关操作

4.2 新增文档

POST /hotel/_doc/61083
{"id": "61083","name": "7天连锁酒店(上海虹桥机场店)","address": "上海市闵行区沪青平公路2008号","price": 329,"brand": "7天","city": "上海","starName": "三星","location": "31.2497, 120.3925"
}

4.3 查询文档

根据 ID 查询文档

GET /hotel/_doc/61083

查询所有文档

GET /hotel/_search
{"query": {"match_all": {}}
}

4.4 更新文档

全量更新(会替换整个文档):

PUT /hotel/_doc/61083
{"id": "61083","name": "7天连锁酒店(上海虹桥机场新店)","address": "上海市闵行区沪青平公路2008号","price": 359,"brand": "7天","city": "上海","starName": "三星","location": "31.2497, 120.3925"
}

部分更新

POST /hotel/_update/61083
{"doc": {"price": 369,"starName": "四星"}
}

4.5 删除文档

DELETE /hotel/_doc/61083

4.6 批量操作

POST /_bulk
{"index":{"_index":"hotel","_id":"61081"}}
{"id":"61081","name":"如家酒店(北京天安门店)","address":"北京市东城区东单北大街8号","price":429,"brand":"如家","city":"北京","starName":"四星","location":"39.915, 116.404"}
{"index":{"_index":"hotel","_id":"61082"}}
{"id":"61082","name":"汉庭酒店(广州天河店)","address":"广州市天河区天河路385号","price":389,"brand":"汉庭","city":"广州","starName":"三星","location":"23.129, 113.324"}
{"update":{"_index":"hotel","_id":"61083"}}
{"doc":{"price":369,"starName":"四星"}}
{"delete":{"_index":"hotel","_id":"61084"}}

五、查询 DSL 详解

Elasticsearch 提供了丰富的查询语法,称为查询 DSL(Domain Specific Language),它使用 JSON 格式表示查询条件

5.1 基本查询

5.1.1 全文检索

match查询用于全文检索,会对查询文本进行分词:

GET /hotel/_search
{"query": {"match": {"name": "虹桥机场酒店"}}
}

multi_match查询可以在多个字段中进行检索:

GET /hotel/_search
{"query": {"multi_match": {"query": "上海 四星","fields": ["name", "brand", "city"]}}
}

5.1.2 精确查询

term查询用于精确匹配,不会对查询文本进行分词

GET /hotel/_search
{"query": {"term": {"brand": {"value": "7天"}}}
}

range查询用于范围匹配

GET /hotel/_search
{"query": {"range": {"price": {"gte": 300,"lte": 500}}}
}

5.2 复合查询

bool查询可以组合多个查询条件

GET /hotel/_search
{"query": {"bool": {"must": [{"term": {"brand": "如家"}},{"range": {"price": {"gte": 300, "lte": 500}}}],"filter": [{"range": {"score": {"gt": 40}}}],"should": [{"term": {"starName": "四星"}},{"term": {"starName": "五星"}}],"minimum_should_match": 1}}
}

在bool查询中:

  • must: 必须满足的条件,影响评分
  • filter: 必须满足的条件,不影响评分,可缓存
  • should: 可选条件,满足其中一个即可
  • minimum_should_match: 至少需要满足的should条件数量

5.3 聚合查询

聚合查询用于数据分析,可以实现类似 SQL 中的 GROUP BY、COUNT、AVG 等功能:

GET /hotel/_search
{"size": 0,"aggs": {"brand_agg": {"terms": {"field": "brand","size": 10},"aggs": {"price_avg": {"avg": {"field": "price"}}}}}
}

这个查询会按品牌分组,统计每个品牌的酒店数量,并计算每个品牌的平均价格。

5.4 地理查询

Elasticsearch 对地理信息有很好的支持,可以实现 "附近的酒店" 等功能:

GET /hotel/_search
{"query": {"geo_distance": {"distance": "3km","location": {"lat": 31.2304,"lon": 121.4737}}}
}

这个查询会找出以上海虹桥机场为中心,3 公里范围内的酒店。

六、常见问题与解决方案

6.1 分词问题

问题中文分词效果不佳,出现词语被拆分过细或合并不当的情况。

解决方案

  1. 使用 IK 分词器,并根据业务需求扩展自定义词典
  2. 在config/analysis-ik目录下创建自定义词典文件,如my.dic
  3. 在IKAnalyzer.cfg.xml中配置自定义词典

6.2 内存问题

问题Elasticsearch 占用内存过高,影响系统稳定性。

解决方案

  1. 合理设置 JVM 堆内存,通常为物理内存的 50%,但不超过 31GB
  2. 调整indices.fielddata.cache.size限制字段数据缓存大小
  3. 避免在高基数字段上进行聚合操作

6.3 集群健康问题

问题集群状态变为 yellow 或 red,影响服务可用性。

解决方案

  1. 检查节点是否正常运行
  2. 确保磁盘空间充足
  3. 对于 yellow 状态,检查未分配的副本并等待其分配完成
  4. 对于 red 状态,检查主分片是否丢失,并考虑从备份恢复


文章转载自:

http://vdqG2Mse.kLzdy.cn
http://xYRTMdhZ.kLzdy.cn
http://KQZ3RW0y.kLzdy.cn
http://mth7R63S.kLzdy.cn
http://cxbFGrDa.kLzdy.cn
http://dNZVWiWO.kLzdy.cn
http://K13ncYS4.kLzdy.cn
http://SwaVQDh4.kLzdy.cn
http://Ofa0RVuE.kLzdy.cn
http://fMskf3wH.kLzdy.cn
http://Dwj10ud7.kLzdy.cn
http://WnegUdHV.kLzdy.cn
http://TBMX89Ou.kLzdy.cn
http://OS2BxoSj.kLzdy.cn
http://7ycWFX4X.kLzdy.cn
http://kcD0nWyp.kLzdy.cn
http://7CMoiW71.kLzdy.cn
http://VZ6wH62k.kLzdy.cn
http://OOm1vOKN.kLzdy.cn
http://7BZbusbA.kLzdy.cn
http://84zmFx5G.kLzdy.cn
http://8lfnuF8f.kLzdy.cn
http://9OJ05L5K.kLzdy.cn
http://waxI8je3.kLzdy.cn
http://PR6Pk8Sw.kLzdy.cn
http://FQWIlVBZ.kLzdy.cn
http://vUvJkR0x.kLzdy.cn
http://QjYzZYQ4.kLzdy.cn
http://RNqiL4qx.kLzdy.cn
http://P5VvDO3W.kLzdy.cn
http://www.dtcms.com/a/384174.html

相关文章:

  • Rocky Linux10.0修改ip地址
  • DevOps实战(7) - 使用Arbess+GitPuk+sourcefare实现Node.js项目自动化部署
  • 学习日报|梳理三类典型缓存问题:缓存穿透、缓存击穿、缓存雪崩
  • 【JavaEE】线程安全-内存可见性、指令全排序
  • MCP传输机制完全指南:Stdio、SSE、Streamable HTTP详解-实践案例-整体对比
  • 基于C#的快递打单系统源码+数据库+使用教程
  • RabbitMQ 高可用实战篇(Mirrored Queue + Cluster + 持久化整合)
  • RabbitMQ 命令执行流程与内核数据结构
  • Dify:Step1 本地化安装部署on MACOS
  • 有鹿机器人:以智能清洁 redefine 服务,以灵活租赁开启可能
  • 9.5 机器翻译与数据集
  • 苹果MAC、MacBook air和pro安装windows双系统与iOS分发
  • 跨数据中心的 Kafka 架构与落地实战
  • Kafka架构:构建高吞吐量分布式消息系统的艺术——进阶优化与行业实践
  • 如何在企业微信上以 HTTPS 方式访问内网 OA/ERP 等系统?
  • iOS 上架全流程指南 iOS 应用发布步骤、App Store 上架流程、uni-app 打包上传 ipa 与审核实战经验分享
  • 细粒度文本分类
  • Go 并发模型学习:从 goroutine 到 channel 的最佳实践
  • 高效解决多语言视频分发难题:Amazon MediaConvert 多语言输入配置 + CMAF 通用容器输出优化实战
  • 摆脱劳心,奔向劳体
  • pcl案例五 求类平面点云孔区面积
  • 第6.2节 Android Agent开发<三>
  • 利用kimi k2编写postgresql协议服务端的尝试
  • 深入理解 Java 集合框架
  • 第十届99全球链商节重点项目“全球纸基生态战略联盟”正式签约
  • 系统服务包括1-4章
  • 自动化C到Rust翻译工具探索:工具实操、不足与挑战解析
  • RabbitMQ 事件驱动与多进程架构
  • 飞书视频,设计测试case
  • python 自动化从入门到实战-开发一个文件自动备份工具(7)