jeakboy 2025-12-05 11:52 采纳率: 56.8%
浏览 3

Elasticsearch的倒排索引在全文搜索中的工作原理是什么? 如何通过分词器和映射优化查询性能?

Elasticsearch的倒排索引在全文搜索中的工作原理是什么? 如何通过分词器和映射优化查询性能?

  • 写回答

4条回答 默认 最新

  • 檀越@新空间 2025-12-05 12:05
    关注

    中午好🌞🌞🌞
    本答案参考通义千问

    Elasticsearch 的 倒排索引(Inverted Index) 是其全文搜索的核心机制,它使得在大量文本数据中快速查找匹配项成为可能。下面我们详细解释其工作原理,并探讨如何通过 分词器(Analyzer)映射(Mapping) 来优化查询性能。


    一、Elasticsearch 倒排索引的工作原理

    1. 什么是倒排索引?

    倒排索引是相对于“正向索引”而言的。

    • 正向索引:以文档为单位,记录每个文档包含哪些词语。
    • 倒排索引:以词语为单位,记录哪些文档包含该词语。

    例如:

    | 文档ID | 内容 | |--------|--------------------------| | doc1 | Elasticsearch 是搜索引擎 | | doc2 | 你正在使用 ElasticSearch |

    倒排索引如下:

    | 词语 | 包含的文档ID | |--------------|--------------| | Elasticsearch | doc1, doc2 | | 是 | doc1 | | 搜索引擎 | doc1 | | 你 | doc2 | | 正在 | doc2 | | 使用 | doc2 | | ElasticSearch| doc2 |

    2. 倒排索引的构建过程

    Elasticsearch 在索引文档时会执行以下步骤:

    1. 分词(Tokenization):将文本拆分成一个个“词项”(term),如“Elasticsearch”会被切分为“Elasticsearch”。
    2. 过滤(Filtering):去除停用词(如“是”、“的”等无意义词)。
    3. 标准化(Normalization):如转小写、去除标点、同义词替换等。
    4. 建立倒排索引:为每个词项建立一个文档列表,记录哪些文档包含该词项。

    3. 搜索过程

    当用户进行搜索时,Elasticsearch 会:

    • 将查询字符串按相同的分词规则处理;
    • 找到对应的词项;
    • 查找这些词项在倒排索引中的文档列表;
    • 最后对这些文档进行排序和返回。

    二、如何通过分词器和映射优化查询性能?

    1. 选择合适的分词器(Analyzer)

    分词器决定了文本如何被切分成词项。选择合适的分词器可以显著提升搜索效率和准确性。

    ✅ 推荐做法:

    • 使用标准分词器(standard analyzer):适用于英文,能正确分割单词和数字。
    • 使用 IK 分词器(中文场景):对中文进行更精细的分词,提高查全率。
    • 自定义分词器:根据业务需求定制分词逻辑。

    示例代码(配置 IK 分词器):

    PUT /my_index
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "ik_analyzer": {
              "type": "custom",
              "tokenizer": "ik_max_word"
            }
          }
        }
      },
      "mappings": {
        "properties": {
          "content": {
            "type": "text",
            "analyzer": "ik_analyzer",
            "search_analyzer": "ik_smart"
          }
        }
      }
    }
    

    说明

    • ik_max_word:最大分词模式,适合索引阶段。
    • ik_smart:智能分词模式,适合搜索阶段。

    2. 合理设计映射(Mapping)

    映射定义了字段的数据类型和索引方式,直接影响查询性能。

    ✅ 推荐做法:

    • 区分 textkeyword 字段
      • text:用于全文搜索,会被分词。
      • keyword:用于精确匹配、聚合、排序等,不被分词。

    示例代码(设置 textkeyword):

    PUT /my_index
    {
      "mappings": {
        "properties": {
          "title": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword"
              }
            }
          },
          "author": {
            "type": "keyword"
          }
        }
      }
    }
    

    说明

    • title 可用于全文搜索(如模糊匹配)。
    • title.keyword 可用于精确匹配或聚合。

    3. 避免过度索引(Avoid Over-Indexing)

    • 只对需要搜索的字段建立索引,避免不必要的字段占用资源。
    • 禁用不需要的字段,如 _sourcestore 等。

    示例代码(禁用 _source):

    PUT /my_index
    {
      "settings": {
        "source": {
          "enabled": false
        }
      },
      "mappings": {
        "properties": {
          "content": { "type": "text" }
        }
      }
    }
    

    说明

    • 如果不需要获取原始数据,可以禁用 _source,节省存储空间和内存。

    4. 使用多字段(Multi-fields)

    对于某些字段,可能需要不同的分析方式。例如,一个字段既需要全文搜索,也需要用于排序或聚合。

    示例代码(多字段):

    PUT /my_index
    {
      "mappings": {
        "properties": {
          "description": {
            "type": "text",
            "fields": {
              "raw": {
                "type": "keyword"
              }
            }
          }
        }
      }
    }
    

    说明

    • description 用于全文搜索。
    • description.raw 用于精确匹配或排序。

    三、总结:优化查询性能的关键点

    1. 选择合适的分词器,确保文本被正确切分。
    2. 合理设计映射,区分 textkeyword 字段。
    3. 避免过度索引,只对必要字段建立索引。
    4. 使用多字段,满足不同查询需求。
    5. 定期清理和重建索引,保持索引效率。

    四、示例:优化后的索引配置

    PUT /optimized_index
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "ik_analyzer": {
              "type": "custom",
              "tokenizer": "ik_max_word",
              "filter": ["lowercase"]
            }
          }
        },
        "source": {
          "enabled": false
        }
      },
      "mappings": {
        "properties": {
          "title": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword"
              }
            }
          },
          "content": {
            "type": "text",
            "analyzer": "ik_analyzer",
            "search_analyzer": "ik_smart"
          },
          "tags": {
            "type": "keyword"
          }
        }
      }
    }
    

    说明

    • 使用了 IK 分词器并启用了 lowercase 过滤。
    • 禁用了 _source
    • title 设置了 keyword 子字段。
    • tags 字段用于精确匹配。

    如果你有具体的业务场景或数据结构,我可以进一步帮助你设计更优化的索引策略。

    评论

报告相同问题?

问题事件

  • 创建了问题 12月5日