Elasticsearch 自定义分词同义词环节的这个细节不大好理解......

2021-04-12 16:39:02 浏览数 (1)

1、问题引出

球友认证考试前一天晚上提问:

扩展背景描述:

这是 Elasticsearch 自定义分词 Text analysis 章节 Token filter reference 小节的 同义词 token 过滤 (Synonym token filter)的一个参数。

的确,官方文档讲解的不详细。

我们彻底解读一下。

2、自定义分词基础认知

如果读者们对自定义分词的实现有疑问,推荐阅读:

Elasticsearch自定义分词,从一个问题说开去

3、给个实战例子,一探究竟

3.1 自定义分词 DSL

代码语言:javascript复制
PUT test_index
{
  "settings": {
    "index": {
      "analysis": {
        "analyzer": {
          "synonym": {
            "tokenizer": "whitespace",
            "filter": [
              "synonym"
            ]
          }
        },
        "filter": {
          "synonym": {
            "type": "synonym",
            "lenient": true,
            "synonyms": [
              "ipod, i-pod, i pod"
            ]
          }
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "synonym"
      }
    }
  }
}

解读如下:

如图所示,结合前面的 DSL 定义。

  • 自定义分词器的名字:synonym。
  • tokenizer 使用:whitespace 空白分词器。
  • filter 也就是 token filter 使用:synonym 同义词实现。

而空白分隔分词器的本质,举例如下:

代码语言:javascript复制
POST _analyze
{
  "analyzer": "whitespace",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

分词后的结果为:

The

2

QUICK

Brown-Foxes

jumped

over

the

lazy

dog's

bone.

概括一下:空格分词器在遇到空格字符时会将文本分解为多个词,仅以空格作为分词分隔单元。

3.2 token filter 细节参数解读

  • 参数 1 —— "type": "synonym"

含义:同义词类型。

  • 参数 2 ——"lenient": true

含义:如果为 true,则在解析同义词配置时会忽略异常。重要的是要注意,只有那些无法解析的同义词规则才被忽略。

默认值:false。

  • 参数 3 —— "synonyms"

指定同义词,也就是指定谁和谁成为同义词。

  • 参数4 ——“expand ”

这个就是文章开头提及的参数,缺省值就是 true。所以上述 DSL 并没有显示指定。

那参数:expand 到底啥意思呢?

4、通过对比,认清 expand 含义

4.1 验证 DSL

代码语言:javascript复制
POST test_index/_doc/1
{"title":"ipod is my love"}

POST test_index/_doc/2
{"title":"i-pod is my love"}

POST test_index/_doc/3
{"title":"i pod is my love"}

POST test_index/_search
{
  "query": {
    "match": {
      "title": "ipod"
    }
  }
}

POST test_index/_search
{
  "query": {
    "match": {
      "title": "i-pod"
    }
  }
}

POST test_index/_search
{
  "query": {
    "match": {
      "title": "i pod"
    }
  }
}

4.2 expand设置为 true

默认值,无需指定即可生效。

分词验证一把:

代码语言:javascript复制
POST test_index/_analyze
{
  "text":"i pod is my love",
  "analyzer": "synonym"
}

结论截图如下:

执行 4.1 的 DSL,检索任何一个,全量三个文档都能返回。

ipod, i-pod, i pod 的含义如下:

具体意思:

  • ipod 等价于 ipod, i-pod, i pod 三个的每一个。
  • i-pod等价于 ipod, i-pod, i pod 三个的每一个。
  • i pod 等价于 ipod, i-pod, i pod 三个的每一个。

而,"ipod, i-pod, i pod => ipod"的含义如下:

代码语言:javascript复制
POST test_index/_analyze
{
  "text":"i pod is my love",
  "analyzer": "synonym"
}

进一步解读为:

  • ipod 仅等价于 ipod,。
  • i-pod 仅等价于 ipod,。
  • i pod 仅等价于 ipod,。

4.3 expand设置为 false

代码语言:javascript复制
DELETE test_index
PUT test_index
{
  "settings": {
    "index": {
      "analysis": {
        "analyzer": {
          "synonym": {
            "tokenizer": "whitespace",
            "filter": [
              "synonym"
            ]
          }
        },
        "filter": {
          "synonym": {
            "type": "synonym",
            "expand":false,
            "lenient": true,
            "synonyms": [
              "ipod, i-pod, i pod"
            ]
          }
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "synonym"
      }
    }
  }
}

POST test_index/_analyze
{
  "text":"i pod is my love",
  "analyzer": "synonym"
}


POST test_index/_analyze
{
  "text":"i-pod is my love",
  "analyzer": "synonym"
}

上述最后两个 analyze 分词结果为:

ipod, i-pod, i pod 的含义如下:ipod, i-pod, i pod 和 ipod 等价。具体意思:

  • ipod 仅 等价于 ipod一个。
  • i-pod 仅 等价于 ipod一个。
  • i pod 仅 等价于 ipod一个。

"ipod, i-pod, i pod => ipod"的含义同 4.2 解读,不再赘述。

5、有了结论再看官方文档

expand 是扩展的意思。

  • 如果为 true,支持扩展,和每一个同义词是同义词。
  • 如果为 false,不支持扩展,仅和最后指向的同义词同义。

6、小结

实践一把,探究真相!

和你一起,死磕 Elastic!

Elastic 核心知识点脑图解读,助力快速建立全局知识体系!

0 人点赞