Elasticsearch 中的 Synonym Token Filter 与 Mapping Char Filter 的区别

1,474 阅读1分钟
  1. 首先这两个的类型不同,Synonym 是一种 Token Filter,而 Mapping 是一种 Character Filter。

  2. 基于上述第一点描述,可以知道两者的执行顺序也不同。由于在 analyzer 分析的过程中先执行 Character Filter 进行字符处理,再执行 Tokenizers 进行分词,最后执行 Token Filters 对分词进行处理。所以先执行 Mapping ,后执行 Synonym 。

  3. 在概念上不同,Synonym 是用来处理同义词的,而 Mapping 是用来处理 key 和对应的 value 转换(个人感觉其实不考虑概念的话,这两个某种程度上差不多)。

  4. 在用法上不同,Synonym 可以使用以下几种方式:

     "synonyms" : ["大家好,你好 => hello",
                  "我们 => we, us",
                  "可可,keke,hehe"]
    

    而 Mapping 则只能使用以下方式:

      "mappings": [
                   "哈哈 => 呵呵",
                   ":( => 生气"
                 ]
    
  5. 两者可以组合使用,如下:

     PUT /test_index
     {
         "settings": {
             "index" : {
                 "analysis" : {
                     "analyzer" : {
                         "my_analyzer" : {
                             "tokenizer" : "standard",
                             "filter" :  "synonym",
                             "char_filter": "my_char_filter"
                         }
                     },
                     "char_filter": {
                       "my_char_filter": {
                         "type": "mapping",
                         "mappings": [
                           "hi => 大家好",
                           "<:> => 我们"
                         ]
                       }
                     },
                     "filter" : {
                         "synonym" : {
                             "type" : "synonym",
                             "lenient": true,
                             "synonyms" : ["大家好,你好 => hello",
                                           "我们 => we, us",
                                           "可可,keke,hehe"]
                         }
                     }
                 }
             }
         }
     }
    

在终端 kibana 执行以下代码:

GET /test_index/_analyze
{
  "text": "<:>大家庭",
  "analyzer": "my_analyzer"
}

得到如下结果:

{
  "tokens" : [
    {
      "token" : "we",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "SYNONYM",
      "position" : 0
    },
    {
      "token" : "us",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "SYNONYM",
      "position" : 0
    },
    {
      "token" : "大",
      "start_offset" : 3,
      "end_offset" : 4,
      "type" : "<IDEOGRAPHIC>",
      "position" : 1
    },
    {
      "token" : "家",
      "start_offset" : 4,
      "end_offset" : 5,
      "type" : "<IDEOGRAPHIC>",
      "position" : 2
    },
    {
      "token" : "庭",
      "start_offset" : 5,
      "end_offset" : 6,
      "type" : "<IDEOGRAPHIC>",
      "position" : 3
    }
  ]
}

可以看到 <:> 先通过 Mapping 转换成了“我们”,然后又通过 Synonym 转换成了 "we" 和 "us" 。