构建拼音索引
Step 1 在ES中安装pinyin分词器
安装步骤详见网上的众多介绍,这里不赘述,ES-pinyin分词器安装。pinyin的开源见:GitHub - medcl/elasticsearch-analysis-pinyin: This Pinyin Analysis plugin is used to do conversionb
Step 2 新建索引并初始化测试数据
PUT idx_test_user
{
"mappings": {
"dynamic": false,
"properties": {
"name": {
"analyzer": "standard",
"type": "text",
"fields": {
"pinyin": {
"type": "text",
"analyzer": "index_pinyin_analyzer"
}
}
}
}
},
"settings": {
"analysis": {
"analyzer": {
"index_pinyin_analyzer": { // MARK 1
"tokenizer": "index_pinyin_tokenizer"
},
"search_pinyin_analyzer": { // MARK 2
"tokenizer": "search_pinyin_tokenzier"
}
},
"tokenizer": {
"index_pinyin_tokenizer": {
"keep_joined_full_pinyin" : "true",
"lowercase" : "true",
"none_chinese_pinyin_tokenize" : "false",
"keep_none_chinese_in_joined_full_pinyin" : "true",
"keep_original" : "true",
"keep_none_chinese_together" : "true",
"remove_duplicated_term" : "false",
"keep_separate_first_letter" : "false",
"type" : "pinyin",
"limit_first_letter_length" : "16",
"keep_full_pinyin" : "true"
},
"search_pinyin_tokenzier": {
"keep_joined_full_pinyin" : "true",
"lowercase" : "true",
"keep_original" : "true",
"remove_duplicated_term" : "false",
"keep_separate_first_letter" : "false",
"type" : "pinyin",
"limit_first_letter_length" : "16",
"keep_full_pinyin" : "true"
}
}
}
}
}
POST idx_test_user/_doc/1
{
"name": "李超"
}
POST idx_test_user/_doc/2
{
"name": "李超越"
}
POST idx_test_user/_doc/3
{
"name": "刘超"
}
POST idx_test_user/_doc/4
{
"name": "李朝"
}
代码示例 1.1
【MARK 1说明】analyzer根据使用的位置不同(索引侧、召回侧),有可能需要定义不同的analyzer,两侧的analyzer搭配在一起使用,共同构成一组搜索策略。MARK 1处为索引侧analyzer
【MARK 2说明】该analyzer用于召回侧,与MARK 1的analyzer组合在一起使用
索引侧analyzer效果说明
以代码示例1.1中的测试数据为例,在倒排索引中的结果是这样的
| token | doc:李超 | doc:李超越 | doc:刘超 | doc:李朝 |
| li | "start_offset" : 0, "end_offset" : 0, "position" : 0 | "start_offset" : 0, "end_offset" : 0, "position" : 0 | - | "start_offset" : 0, "end_offset" : 0, "position" : 0 |
| 李超 | "start_offset" : 0, "end_offset" : 0, "position" : 0 | - | - | - |
| lichao | "start_offset" : 0, "end_offset" : 0, "position" : 0 | - | - | "start_offset" : 0, "end_offset" : 0, "position" : 0 |
| lc | "start_offset" : 0, "end_offset" : 0, "position" : 0 | - | "start_offset" : 0, "end_offset" : 0, "position" : 0 | "start_offset" : 0, "end_offset" : 0, "position" : 0 |
| chao | "start_offset" : 0, "end_offset" : 0, "position" : 1 | "start_offset" : 0, "end_offset" : 0, "position" : 1 | "start_offset" : 0, "end_offset" : 0, "position" : 1 | "start_offset" : 0, "end_offset" : 0, "position" : 1 |
| 李超越 | - | "start_offset" : 0, "end_offset" : 0, "position" : 0 | - | - |
| lichaoyue | - | "start_offset" : 0, "end_offset" : 0, "position" : 0 | - | - |
| lcy | - | "start_offset" : 0, "end_offset" : 0, "position" : 0 | - | - |
| yue | - | "start_offset" : 0, "end_offset" : 0, "position" : 2 | - | - |
| liu | - | - | "start_offset" : 0, "end_offset" : 0, "position" : 0 | - |
| 刘超 | - | - | "start_offset" : 0, "end_offset" : 0, "position" : 0 | - |
| liuchao | - | - | "start_offset" : 0, "end_offset" : 0, "position" : 0 | - |
| 李朝 | - | - | - | "start_offset" : 0, "end_offset" : 0, "position" : 0 |
表 1.1 「李超」、「李超越」、「刘超」在倒排索引中的结构
召回侧实现方式
"match_phrase": { // MARK 1
"name.pinyin": {
"analyzer": "search_pinyin_analyzer", // MARK 2
"query": "lichao"
}
}
代码示例 2.1
【MARK 1说明】注意要使用match_phrase,而不是match,不然会有badcase
【MARK 2说明】注意这里要指定召回侧的analyzer,analyzer声明详见「代码示例 1.1」,若不指定则会用ES默认analyzer:standard
拼音搜索策略及其效果
使用代码示例1.1中提供的数据,倒排索引结构见表1.1,召回DSL见代码示例2.1
| query | 全拼 | 连字拼音 | 前缀拼音 | 多音字 |
| lichao | 李超,李朝 | 李超越 | - | - |
| lichaoyue | 李超越 | - | - | - |
| li | - | 李超,李超越,李朝 | - | - |
| chao | - | 李超,李超越,刘超,李朝 | - | - |
| yue | - | 李超越 | - | - |
| liuchao | 刘超 | - | - | - |
| liu | - | 刘超 | - | - |
| lc | - | - | 不支持 | - |
| lizhao | - | - | - | 不支持,无法召回李朝 |
表 2.1 各query在不同策略下可以召回的结果
欢迎访问我的博客:用ES实现拼音搜索策略 百木森森的技术分享
本文介绍了如何在Elasticsearch(ES)中实现拼音搜索策略,包括安装pinyin分词器,新建索引并初始化测试数据,以及在索引和召回侧的analyzer配置。通过示例代码展示了匹配和召回的效果,探讨了不同查询策略下召回的结果。

7639

被折叠的 条评论
为什么被折叠?



