拼音分词器

拼音分词器 #

总体介绍 #

pinyin-analyzer 拼音分词器能够在索引阶段将 中文字符实时转写为拼音,并在检索阶段对拼音、汉字及混输查询进行统一匹配。借助该插件,你可以轻松实现:

  • 支持 全拼首字母全拼拼接 等多种检索方式;
  • 保留非中文字符,实现「中英混输」搜索;
  • 借助 token filter 在分词链中灵活组合不同策略;
  • 在联想输入、排序、聚合等场景下提升中文用户体验。

适用于人名、地名、品牌、歌曲、商品等多种中文文本检索场景。

参数说明 #

下表整理了 pinyin 分词器 / 过滤器支持的全部可选参数及默认值。

参数说明默认值
keep_first_letter仅保留每个汉字的拼音首字母。例如 刘德华ldhtrue
keep_separate_first_letter将首字母分开存储,提高命中率。例如 刘德华l, d, h,注意:这可能会由于词频增加而增加查询模糊性。false
limit_first_letter_length首字母结果最长长度16
keep_full_pinyin保留每个汉字的全拼。如 刘德华liu, de, huatrue
keep_joined_full_pinyin将全拼连接在一起。如 刘德华liudehuafalse
keep_none_chinese保留非中文字符(数字/字母等)true
keep_none_chinese_together将连续非中文字符作为整体保留。例如, DJ 音乐家 变成 DJ 、 yin 、 yue 、 jia 。当设置为 false 时, DJ 音乐家 变成 D 、 J 、 yin 、 yue 、 jia 。注意: keep_none_chinese 应该先启用。true
keep_none_chinese_in_first_letter在首字母结果中保留非中文字。例如, 刘德华 AT2016 变成 ldhat2016 。符true
keep_none_chinese_in_joined_full_pinyin在拼接全部拼音时保留非中文字。例如, 刘德华 2016 变成 liudehua2016 。符false
none_chinese_pinyin_tokenize将非中文字符中可能的拼音继续拆分例如, liudehuaalibaba13zhuanghan 变成 liu 、 de 、 hua 、 a 、 li 、 ba 、 ba 、 13 、 zhuang 、 han 。注意: keep_none_chinese 和 keep_none_chinese_together 应该先启用。true
keep_original同时保留原始文本false
lowercase对非中文字符强制小写true
trim_whitespace去除首尾空格true
remove_duplicated_term开启时,移除重复术语以节省索引空间。例如, de 的 变为 de 。注意:位置相关的查询可能会受影响。积false
ignore_pinyin_offset忽略 offset 以允许重叠 token。在 6.0 版本之后,偏移量受到严格限制,不允许重叠的标记。使用此参数,通过忽略偏移量将允许重叠的标记。请注意,所有与位置相关的查询或高亮将变得不正确。您应该使用多字段,并为不同的查询目的指定不同的设置。如果您需要偏移量,请将其设置为 false。true

备注:以上参数可按需自由组合。若使用 token filter,请将其放置于自定义分词链中。


常见用例 #

创建索引并配置自定义 Pinyin Analyzer #

PUT /medcl
{
  "settings": {
    "analysis": {
      "tokenizer": {
        "my_pinyin": {
          "type": "pinyin",
          "keep_separate_first_letter": false,
          "keep_full_pinyin": true,
          "keep_original": true,
          "limit_first_letter_length": 16,
          "lowercase": true,
          "remove_duplicated_term": true
        }
      },
      "analyzer": {
        "pinyin_analyzer": {
          "tokenizer": "my_pinyin"
        }
      }
    }
  }
}

测试分词效果

GET /medcl/_analyze
{
  "text": ["刘德华"],
  "analyzer": "pinyin_analyzer"
}

预期返回:

{
  "tokens": [
    {
      "token": "liu",
      "start_offset": 0,
      "end_offset": 1,
      "type": "word",
      "position": 0
    },
    {
      "token": "de",
      "start_offset": 1,
      "end_offset": 2,
      "type": "word",
      "position": 1
    },
    {
      "token": "hua",
      "start_offset": 2,
      "end_offset": 3,
      "type": "word",
      "position": 2
    },
    {
      "token": "刘德华",
      "start_offset": 0,
      "end_offset": 3,
      "type": "word",
      "position": 3
    },
    {
      "token": "ldh",
      "start_offset": 0,
      "end_offset": 3,
      "type": "word",
      "position": 4
    }
  ]
}

创建字段映射并建立文档 #

直接使用拼音分词器

POST /medcl/_mapping
{
        "properties": {
            "name": {
                "type": "keyword",
                "fields": {
                    "pinyin": {
                        "type": "text",
                        "store": false,
                        "term_vector": "with_offsets",
                        "analyzer": "pinyin_analyzer",
                        "boost": 10
                    }
                }
            }
        }

}

## 索引一个文档

POST /medcl/_create/andy
{"name":"刘德华"}

## 查询测试

curl http://localhost:9200/medcl/_search?q=name:%E5%88%98%E5%BE%B7%E5%8D%8E
curl http://localhost:9200/medcl/_search?q=name.pinyin:%e5%88%98%e5%be%b7
curl http://localhost:9200/medcl/_search?q=name.pinyin:liu
curl http://localhost:9200/medcl/_search?q=name.pinyin:ldh
curl http://localhost:9200/medcl/_search?q=name.pinyin:de+hua

使用 Pinyin-TokenFilter #

PUT /medcl1/
{
    "settings" : {
        "analysis" : {
            "analyzer" : {
                "user_name_analyzer" : {
                    "tokenizer" : "whitespace",
                    "filter" : "pinyin_first_letter_and_full_pinyin_filter"
                }
            },
            "filter" : {
                "pinyin_first_letter_and_full_pinyin_filter" : {
                    "type" : "pinyin",
                    "keep_first_letter" : true,
                    "keep_full_pinyin" : false,
                    "keep_none_chinese" : true,
                    "keep_original" : false,
                    "limit_first_letter_length" : 16,
                    "lowercase" : true,
                    "trim_whitespace" : true,
                    "keep_none_chinese_in_first_letter" : true
                }
            }
        }
    }
}

Token 测试:刘德华 张学友 郭富城 黎明 四大天王

GET /medcl1/_analyze
{
  "text": ["刘德华 张学友 郭富城 黎明 四大天王"],
  "analyzer": "user_name_analyzer"
}
{
  "tokens" : [
    {
      "token" : "ldh",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "zxy",
      "start_offset" : 4,
      "end_offset" : 7,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "gfc",
      "start_offset" : 8,
      "end_offset" : 11,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "lm",
      "start_offset" : 12,
      "end_offset" : 14,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "sdtw",
      "start_offset" : 15,
      "end_offset" : 19,
      "type" : "word",
      "position" : 4
    }
  ]
}

短语查询 #

场景 1:全拼音查询

PUT /medcl2/
{
    "settings" : {
        "analysis" : {
            "analyzer" : {
                "pinyin_analyzer" : {
                    "tokenizer" : "my_pinyin"
                    }
            },
            "tokenizer" : {
                "my_pinyin" : {
                    "type" : "pinyin",
                    "keep_first_letter":false,
                    "keep_separate_first_letter" : false,
                    "keep_full_pinyin" : true,
                    "keep_original" : false,
                    "limit_first_letter_length" : 16,
                    "lowercase" : true
                }
            }
        }
    }
}

POST /medcl2/_mapping
{
  "properties": {
      "name": {
          "type": "keyword",
          "fields": {
              "pinyin": {
                  "type": "text",
                  "store": false,
                  "term_vector": "with_offsets",
                  "analyzer": "pinyin_analyzer",
                  "boost": 10
              }
          }
      }
  }
}

POST /medcl2/_doc?refresh=true
{"name":"liudehua"}


GET /medcl2/_search
{
  "query": {
    "match_phrase": {
      "name.pinyin": "刘德华"
    }
  }
}

场景 2:全拼/缩写/混写等多场景匹配

PUT /medcl3/
{
   "settings" : {
       "analysis" : {
           "analyzer" : {
               "pinyin_analyzer" : {
                   "tokenizer" : "my_pinyin"
                   }
           },
           "tokenizer" : {
               "my_pinyin" : {
                   "type" : "pinyin",
                   "keep_first_letter":true,
                   "keep_separate_first_letter" : true,
                   "keep_full_pinyin" : true,
                   "keep_original" : false,
                   "limit_first_letter_length" : 16,
                   "lowercase" : true
               }
           }
       }
   }
}

POST /medcl3/_mapping
{
  "properties": {
      "name": {
          "type": "keyword",
          "fields": {
              "pinyin": {
                  "type": "text",
                  "store": false,
                  "term_vector": "with_offsets",
                  "analyzer": "pinyin_analyzer",
                  "boost": 10
              }
          }
      }
  }
}


GET /medcl3/_analyze
{
   "text": ["刘德华"],
   "analyzer": "pinyin_analyzer"
}

POST /medcl3/_create/andy
{"name":"刘德华"}

GET /medcl3/_search
{
 "query": {"match_phrase": {
   "name.pinyin": "刘德h"
 }}
}

GET /medcl3/_search
{
 "query": {"match_phrase": {
   "name.pinyin": "刘dh"
 }}
}

GET /medcl3/_search
{
 "query": {"match_phrase": {
   "name.pinyin": "liudh"
 }}
}

GET /medcl3/_search
{
 "query": {"match_phrase": {
   "name.pinyin": "liudeh"
 }}
}

GET /medcl3/_search
{
 "query": {"match_phrase": {
   "name.pinyin": "liude华"
 }}
}