Elasticsearch 核心原理介绍

1、Elasticsearch 是什么?

Elasticsearch 是一个基于 Lucene 构建的、开源的、分布式的、RESTful 的搜索和分析引擎。

  • 基于 Lucene: 它的底层核心是 Apache Lucene,一个非常强大、高性能的 Java 搜索引擎库。Elasticsearch 在 Lucene 的基础上,提供了更简单易用的功能和分布式架构。
  • 分布式: 它天生就是分布式的。数据可以被分片并分布到集群中的多个节点上,这使得它能够处理海量数据(PB级别),并提供高可用性和强大的横向扩展能力。
  • 搜索和分析引擎: 它不仅用于传统的全文检索,还非常擅长进行复杂的数据分析,例如聚合操作(Aggregation),可以生成复杂的报表和指标。

常见应用场景:

  • 网站搜索: 电商网站的商品搜索、新闻网站的文章搜索。
  • 日志数据分析 (ELK Stack): 与 Logstash 和 Kibana 组成 ELK 栈,用于收集、存储、分析和可视化日志数据,是运维和开发的利器。
  • 应用性能监控 (APM): 追踪应用程序的性能问题。
  • 企业搜索: 搜索公司内部的各种文档、邮件、数据。

2、核心原理介绍

2.1、分词

分词 是将一段文本切分成一个个独立的、有意义的词条的过程。它是文本处理和搜索的基础。例如:

输入: "我爱北京天安门"
输出: ["我", "爱", "北京", "天安门"]  # 智能分词

分词过程通常包括以下步骤:

  • 字符过滤:使用字符过滤器(Character Filter)对原始文本进行预处理,例如去除HTML标签、替换特殊字符等。
  • 分词:使用分词器(Tokenizer)将文本拆分成单个的词条(tokens)。例如,标准分词器会根据空格和标点将文本分成多个词条。
  • 词条过滤:使用词条过滤器(Token Filter)对分词后的结果进行进一步处理,例如转为小写、删除停用词、添加同义词等。
原始文本
     ↓
字符过滤器(如:去除HTML标签)
     ↓
分词器(按规则切分)
     ↓
词条过滤器(如:转小写、去停用词)
     ↓
最终词条

2.2、核心原理:倒排索引

这是 Elasticsearch 能够实现快速全文搜索的基石。

传统数据库的困境:如果想在内容字段中搜索包含“搜索”的记录,传统数据库会使用 LIKE ‘%搜索%’,这会导致全表扫描,效率极低。

传统数据库使用正排索引(文档 → 词条),而 Elasticsearch 使用倒排索引(词条 → 文档)。

假设有三个文档:

  • 文档1:"苹果公司发布了新手机"
  • 文档2:"这个苹果很好吃"
  • 文档3:"手机市场竞争激烈"

步骤1:文档分词

文档1 → ["苹果", "公司", "发布", "了", "新", "手机"]
文档2 → ["这个", "苹果", "很", "好吃"]  
文档3 → ["手机", "市场", "竞争", "激烈"]

步骤2:标准化处理

  • 去除停用词("了", "这个", "很"等)
  • 统一大小写(如果有英文)
  • 词干提取(如"发布了" → "发布")

步骤3:构建倒排索引表

词条 文档ID列表 位置信息 其他元数据
苹果 [1, 2] 1:[0], 2:[1] {doc_freq: 2}
公司 [1] 1:[1] {doc_freq: 1}
发布 [1] 1:[2] {doc_freq: 1}
[1] 1:[4] {doc_freq: 1}
手机 [1, 3] 1:[5], 3:[0] {doc_freq: 2}
好吃 [2] 2:[3] {doc_freq: 1}
市场 [3] 3:[1] {doc_freq: 1}
竞争 [3] 3:[2] {doc_freq: 1}
激烈 [3] 3:[3] {doc_freq: 1}

2.3、搜索执行流程

例如我们需要搜索查询:"苹果手机"

步骤1:查询解析与分词
查询字符串被分词为:["苹果", "手机"]

步骤2:查找倒排索引

  • 查找"苹果" → 得到文档列表 [1, 2]
  • 查找"手机" → 得到文档列表 [1, 3]

步骤3:结果合并
对于布尔OR查询(默认):取并集 [1, 2, 3]
对于布尔AND查询:取交集 [1]

步骤4:相关性评分(TF-IDF算法)

TF(词频)- 在单个文档中的重要性:

  • 文档1中:"苹果"出现1次,"手机"出现1次
  • 文档2中:"苹果"出现1次,"手机"出现0次
  • 文档3中:"苹果"出现0次,"手机"出现1次

IDF(逆文档频率)- 在整个索引中的重要性:

  • "苹果"的IDF = log(3/2) = 0.176 (3个总文档,2个包含"苹果")
  • "手机"的IDF = log(3/2) = 0.176 (3个总文档,2个包含"手机")

计算得分:

文档1得分 = TF("苹果") × IDF("苹果") + TF("手机") × IDF("手机")
         = 1 × 0.176 + 1 × 0.176 = 0.352
文档2得分 = 1 × 0.176 + 0 × 0.176 = 0.176
文档3得分 = 0 × 0.176 + 1 × 0.176 = 0.176

步骤5:结果排序和返回
按得分排序返回:

  1. 文档1 (得分: 0.352)
  2. 文档2 (得分: 0.176)
  3. 文档3 (得分: 0.176)

这样我们就找到了对应的文档,并可以按得分排序。


3、总结

3.1、索引构建流程(数据准备阶段)
┌─────────────┐    ┌───────────────┐    ┌─────────────┐    ┌────────────────┐
│  输入文本     │ -> │ 文本预处理     │ -> │   分词       │ -> │ 构建倒排索引     │
│             │    │               │    │             │    │                │
│ • 文档数据   │     │ • 大小写转换   │    │ • 中文分词    │    │ • 词条→文档映射 │
│ • JSON格式   │    │ • 去除HTML标签 │    │ • 英文分词    │    │ • 位置信息记录  │
│             │    │ • 特殊字符处理  │    │ • 停用词过滤  │    │ • 词频统计      │
└─────────────┘    └───────────────┘    └─────────────┘    └────────────────┘

示例:

输入: "苹果公司发布了新手机"
预处理: "苹果公司发布了新手机"  
分词: ["苹果", "公司", "发布", "新", "手机"]
倒排索引: 
  "苹果" → [文档1]
  "手机" → [文档1]
  "公司" → [文档1]
  ...
3.2、搜索查询流程(检索阶段)
┌─────────────┐    ┌─────────────┐    ┌────────────────┐    ┌─────────────┐    ┌────────────────┐
│  搜索查询    │ -> │    分词      │ -> │ 查找倒排索引     │ -> │  结果合并    │ -> │ 相关性评分       │
│             │    │             │    │                │    │             │    │                │
│ • 用户输入   │    │ • 查询词分词  │    │ • 多词条并行查找 │    │ • 集合运算    │    │ • TF-IDF/BM25  │
│ • 查询语法   │    │ • 同义词扩展  │    │ • 分布式分片查找 │    │ • 去除重复    │    │ • 位置加权      │
│             │    │             │    │                │    │             │    │ • 字段权重      │
└─────────────┘    └─────────────┘    └────────────────┘    └─────────────┘    └────────────────┘

示例:

查询: "苹果 手机"
分词: ["苹果", "手机"]
查找: 
  "苹果" → [文档1, 文档2]
  "手机" → [文档1, 文档3]
结果合并: [文档1] (AND操作)
相关性评分: 文档1得分最高(包含两个词条)
3.3、完整架构视图
      ┌─────────────────┐              ┌─────────────────┐
      │   索引构建流程    │              │   搜索查询流程    │
      │  (数据准备)      │              │  (检索执行)       │
      ├─────────────────┤              ├─────────────────┤
      │ 输入文本         │              │ 搜索查询          │
      │       ↓         │              │       ↓         │
      │ 文本预处理        │              │ 分词            │
      │       ↓         │              │       ↓         │
      │ 分词             │              │ 查找倒排索引      │
      │       ↓         │              │       ↓         │
      │ 构建倒排索引      │◄─────────────┤ 结果合并         │
      └─────────────────┘  依赖关系     │       ↓         │
                             │         │ 相关性评分        │
                             │         └─────────────────┘
                             │
                   ┌─────────┴─────────┐
                   │  倒排索引存储       │
                   │  (核心数据结构)     │
                   │ • 词条词典         │
                   │ • 文档列表         │
                   │ • 位置信息         │
                   └───────────────────┘
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容