ElasticSearch文档分析

ElasticSearch文档分析 包含下面的过程:

  • 将一块文本分成适合于倒排索引的独立的 词条
  • 将这些词条统一化为标准格式以提高它们的"可搜索性",或者 recall

分析器执行上面的工作。分析器实际上是将三个功能封装到了一个包里:

  • 字符过滤器

首先,字符串按顺序通过每个 字符过滤器 。他们的任务是在分词前整理字符串。一个字符过滤器可以用来去掉HTML,或者将 & 转化成 and。

  • 分词器

其次,字符串被 分词器 分为单个的词条。一个简单的分词器遇到空格和标点的时候,可能会将文本拆分成词条。

  • Token过滤器

最后,词条按顺序通过每个 token 过滤器 。这个过程可能会改变词条(例如,小写化 Quick ),删除词条(例如, 像 a, and, the 等无用词),或者增加词条(例如,像 jump 和 leap 这种同义词)。

1 内置分析器

Elasticsearch还附带了可以直接使用的预包装的分析器。接下来我们会列出最重要的分析器。为了证明它们的差异,我们看看每个分析器会从下面的字符串得到哪些词条:

"Set the shape to semi-transparent by calling set_trans(5)"

  • 标准分析器

标准分析器是Elasticsearch默认使用的分析器。它是分析各种语言文本最常用的选择。它根据 Unicode 联盟 定义的 单词边界 划分文本。删除绝大部分标点。最后,将词条小写。它会产生:

set, the, shape, to, semi, transparent, by, calling, set_trans, 5

  • 简单分析器

简单分析器在任何不是字母的地方分隔文本,将词条小写。它会产生:

set, the, shape, to, semi, transparent, by, calling, set, trans

  • 空格分析器

空格分析器在空格的地方划分文本。它会产生:

Set, the, shape, to, semi-transparent, by, calling, set_trans(5)

  • 语言分析器

特定语言分析器可用于 很多语言。它们可以考虑指定语言的特点。例如, 英语 分析器附带了一组英语无用词(常用单词,例如 and 或者 the ,它们对相关性没有多少影响),它们会被删除。 由于理解英语语法的规则,这个分词器可以提取英语单词的 词干 。

英语 分词器会产生下面的词条:

set, shape, semi, transpar, call, set_tran, 5

注意看 transparent、 calling 和 set_trans 已经变为词根格式

2 分析器使用场景

当我们 索引 一个文档,它的全文域被分析成词条以用来创建倒排索引。 但是,当我们在全文域 搜索 的时候,我们需要将查询字符串通过 相同的分析过程 ,以保证我们搜索的词条格式与索引中的词条格式一致。

全文查询,理解每个域是如何定义的,因此它们可以做正确的事:

  • 当你查询一个 全文 域时, 会对查询字符串应用相同的分析器,以产生正确的搜索词条列表。
  • 当你查询一个 精确值 域时,不会分析查询字符串,而是搜索你指定的精确值。

3 测试分析器

有些时候很难理解分词的过程和实际被存储到索引中的词条,特别是你刚接触Elasticsearch。为了理解发生了什么,你可以使用 analyze API 来看文本是如何被分析的。在消息体里,指定分析器和要分析的文本

复制代码
GET http://localhost:9200/_analyze`
`{`
  `"analyzer":` `"standard",`
  `"text":` `"Text to analyze"`
`}

结果中每个元素代表一个单独的词条:

复制代码
{`
   `"tokens":` `[`
      `{`
         `"token":`        `"text",`
         `"start_offset":` `0,`
         `"end_offset":`   `4,`
         `"type":`         `"<ALPHANUM>",`
         `"position":`     `1`
      `},`
      `{`
         `"token":`        `"to",`
         `"start_offset":` `5,`
         `"end_offset":`   `7,`
         `"type":`         `"<ALPHANUM>",`
         `"position":`     `2`
      `},`
      `{`
         `"token":`        `"analyze",`
         `"start_offset":` `8,`
         `"end_offset":`   `15,`
         `"type":`         `"<ALPHANUM>",`
         `"position":`     `3`
      `}`
   `]`
`}

token 是实际存储到索引中的词条。 position 指明词条在原始文本中出现的位置。 start_offset 和 end_offset 指明字符在原始字符串中的位置。

4 指定分析器

当Elasticsearch在你的文档中检测到一个新的字符串域,它会自动设置其为一个全文 字符串 域,使用 标准 分析器对它进行分析。你不希望总是这样。可能你想使用一个不同的分析器,适用于你的数据使用的语言。有时候你想要一个字符串域就是一个字符串域---不使用分析,直接索引你传入的精确值,例如用户ID或者一个内部的状态域或标签。要做到这一点,我们必须手动指定这些域的映射。

5 IK分词器

首先我们通过Postman发送GET 请求查询分词效果

复制代码
GET http://localhost:9200/_analyze`
`{`
	`"text":"测试单词"`
`}

ES的默认分词器无法识别中文中测试、单词这样的词汇,而是简单的将每个字拆完分为一个词

复制代码
{`
    `"tokens":` `[`
        `{`
            `"token":` `"测",`
            `"start_offset":` `0,`
            `"end_offset":` `1,`
            `"type":` `"<IDEOGRAPHIC>",`
            `"position":` `0`
        `},`
        `{`
            `"token":` `"试",`
            `"start_offset":` `1,`
            `"end_offset":` `2,`
            `"type":` `"<IDEOGRAPHIC>",`
            `"position":` `1`
        `},`
        `{`
            `"token":` `"单",`
            `"start_offset":` `2,`
            `"end_offset":` `3,`
            `"type":` `"<IDEOGRAPHIC>",`
            `"position":` `2`
        `},`
        `{`
            `"token":` `"词",`
            `"start_offset":` `3,`
            `"end_offset":` `4,`
            `"type":` `"<IDEOGRAPHIC>",`
            `"position":` `3`
        `}`
    `]`
`}

这样的结果显然不符合我们的使用要求,所以我们需要下载ES对应版本的中文分词器。

我们这里采用IK中文分词器,下载地址为: https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.8.0

将解压后的后的文件夹放入ES根目录下的plugins目录下,重启ES即可使用。

我们这次加入新的查询参数"analyzer":"ik_max_word"

复制代码
GET http://localhost:9200/_analyze`
`{`
	`"text":"测试单词",`
	`"analyzer":"ik_max_word"`
`}
  • ik_max_word:会将文本做最细粒度的拆分
  • ik_smart:会将文本做最粗粒度的拆分

使用中文分词后的结果为:

复制代码
{`
    `"tokens":` `[`
        `{`
            `"token":` `"测试",`
            `"start_offset":` `0,`
            `"end_offset":` `2,`
            `"type":` `"CN_WORD",`
            `"position":` `0`
        `},`
        `{`
            `"token":` `"单词",`
            `"start_offset":` `2,`
            `"end_offset":` `4,`
            `"type":` `"CN_WORD",`
            `"position":` `1`
        `}`
    `]`
`}

ES中也可以进行扩展词汇,首先查询

复制代码
GET http://localhost:9200/_analyze`
`{`
	`"text":"弗雷尔卓德",`
	`"analyzer":"ik_max_word"`
`}

仅仅可以得到每个字的分词结果,我们需要做的就是使分词器识别到弗雷尔卓德也是一个词语

复制代码
{`
    `"tokens":` `[`
        `{`
            `"token":` `"弗",`
            `"start_offset":` `0,`
            `"end_offset":` `1,`
            `"type":` `"CN_CHAR",`
            `"position":` `0`
        `},`
        `{`
            `"token":` `"雷",`
            `"start_offset":` `1,`
            `"end_offset":` `2,`
            `"type":` `"CN_CHAR",`
            `"position":` `1`
        `},`
        `{`
            `"token":` `"尔",`
            `"start_offset":` `2,`
            `"end_offset":` `3,`
            `"type":` `"CN_CHAR",`
            `"position":` `2`
        `},`
        `{`
            `"token":` `"卓",`
            `"start_offset":` `3,`
            `"end_offset":` `4,`
            `"type":` `"CN_CHAR",`
            `"position":` `3`
        `},`
        `{`
            `"token":` `"德",`
            `"start_offset":` `4,`
            `"end_offset":` `5,`
            `"type":` `"CN_CHAR",`
            `"position":` `4`
        `}`
    `]`
`}`
`

首先进入ES根目录中的plugins文件夹下的ik文件夹,进入config目录,创建custom.dic文件,写入弗雷尔卓德。同时打开IKAnalyzer.cfg.xml文件,将新建的custom.dic配置其中,重启ES服务器。

6 自定义分析器

虽然Elasticsearch带有一些现成的分析器,然而在分析器上Elasticsearch真正的强大之处在于,你可以通过在一个适合你的特定数据的设置之中组合字符过滤器、分词器、词汇单元过滤器来创建自定义的分析器。在 分析与分析器 我们说过,一个 分析器 就是在一个包里面组合了三种函数的一个包装器, 三种函数按照顺序被执行:

  • 字符过滤器

字符过滤器 用来 整理 一个尚未被分词的字符串。例如,如果我们的文本是HTML格式的,它会包含像 <p> 或者 <div> 这样的HTML标签,这些标签是我们不想索引的。我们可以使用 html清除 字符过滤器 来移除掉所有的HTML标签,并且像把 &Aacute; 转换为相对应的Unicode字符 Á 这样,转换HTML实体。一个分析器可能有0个或者多个字符过滤器。

  • 分词器

一个分析器 必须 有一个唯一的分词器。 分词器把字符串分解成单个词条或者词汇单元。 标准 分析器里使用的 标准 分词器 把一个字符串根据单词边界分解成单个词条,并且移除掉大部分的标点符号,然而还有其他不同行为的分词器存在。

例如, 关键词 分词器 完整地输出 接收到的同样的字符串,并不做任何分词。 空格 分词器 只根据空格分割文本 。 正则 分词器 根据匹配正则表达式来分割文本 。

  • 词单元过滤器

经过分词,作为结果的 词单元流 会按照指定的顺序通过指定的词单元过滤器 。

词单元过滤器可以修改、添加或者移除词单元。我们已经提到过 lowercase 和 stop 词过滤器 ,但是在 Elasticsearch 里面还有很多可供选择的词单元过滤器。 词干过滤器 把单词 遏制 为 词干。 ascii_folding 过滤器移除变音符,把一个像 "très" 这样的词转换为 "tres" 。 ngram 和 edge_ngram 词单元过滤器 可以产生 适合用于部分匹配或者自动补全的词单元。

接下来,我们看看如何创建自定义的分析器:

复制代码
PUT http://localhost:9200/my_index`
`{`
    `"settings":` `{`
        `"analysis":` `{`
            `"char_filter":` `{`
                `"&_to_and":` `{`
                    `"type":`       `"mapping",`
                    `"mappings":` `[` `"&=> and "]`
            `}},`
            `"filter":` `{`
                `"my_stopwords":` `{`
                    `"type":`       `"stop",`
                    `"stopwords":` `[` `"the",` `"a"` `]`
            `}},`
            `"analyzer":` `{`
                `"my_analyzer":` `{`
                    `"type":`         `"custom",`
                    `"char_filter":`  `[` `"html_strip",` `"&_to_and"` `],`
                    `"tokenizer":`    `"standard",`
                    `"filter":`       `[` `"lowercase",` `"my_stopwords"` `]`
            `}}`
`}}}

索引被创建以后,使用 analyze API 来 测试这个新的分析器

复制代码
GET http://127.0.0.1:9200/my_index/_analyze`
`{`
    `"text":"The quick & brown fox",`
    `"analyzer":` `"my_analyzer"`
`}

下面的缩略结果展示出我们的分析器正在正确地运行

复制代码
{`
    `"tokens":` `[`
        `{`
            `"token":` `"quick",`
            `"start_offset":` `4,`
            `"end_offset":` `9,`
            `"type":` `"<ALPHANUM>",`
            `"position":` `1`
        `},`
        `{`
            `"token":` `"and",`
            `"start_offset":` `10,`
            `"end_offset":` `11,`
            `"type":` `"<ALPHANUM>",`
            `"position":` `2`
        `},`
        `{`
            `"token":` `"brown",`
            `"start_offset":` `12,`
            `"end_offset":` `17,`
            `"type":` `"<ALPHANUM>",`
            `"position":` `3`
        `},`
        `{`
            `"token":` `"fox",`
            `"start_offset":` `18,`
            `"end_offset":` `21,`
            `"type":` `"<ALPHANUM>",`
            `"position":` `4`
        `}`
    `]`
`}
相关推荐
Elastic 中国社区官方博客5 小时前
使用 Elastic-Agent 或 Beats 将 Journald 中的 syslog 和 auth 日志导入 Elastic Stack
大数据·linux·服务器·elasticsearch·搜索引擎·信息可视化·debian
星星点点洲7 小时前
【RAG】RAG 系统的基本搭建流程(ES关键词检索示例)
python·elasticsearch
@@@wang9 小时前
搜索引擎(基于java在线文档)
搜索引擎
说私域16 小时前
基于开源AI大模型的精准零售模式创新——融合AI智能名片与S2B2C商城小程序源码的“人工智能 + 线下零售”路径探索
人工智能·搜索引擎·小程序·开源·零售
郝开21 小时前
ElasticSearch 分词器介绍及测试:Standard(标准分词器)、English(英文分词器)、Chinese(中文分词器)、IK(IK 分词器)
elasticsearch·中文分词·ik·ik analyzer
kngines1 天前
【实战ES】实战 Elasticsearch:快速上手与深度实践-3.2.3 案例:新闻搜索引擎的相关性优化
大数据·elasticsearch·搜索引擎
天草二十六_简村人1 天前
JPA编程,去重查询ES索引中的字段,对已有数据的去重过滤,而非全部字典数据
java·大数据·spring boot·elasticsearch·搜索引擎·微服务·架构
C182981825751 天前
ES Filter Query 区别
elasticsearch
Elastic 中国社区官方博客1 天前
Elasticsearch:使用 BigQuery 提取数据
大数据·数据库·elasticsearch·搜索引擎·全文检索
小诸葛IT课堂1 天前
MySQL数据实时同步至Elasticsearch的高效方案:Java实现+源码解析,一文搞定!
java·mysql·elasticsearch