Elasticsearch-自动补全
2024-04-09 18:20:42  阅读数 3634

零、本文纲要

  • 一、自动补全
  • 二、使用拼音分词
  • 三、自定义分词器
    1、分词器的组成
    2、使用自定义分词器
  • 四、ES自动补全
    1、completion suggester查询
    2、使用DSL语句进行查询
    3、RestClient实现自动补全

tips:Ctrl + F快速定位所需内容进行阅读吧。

一、自动补全

当用户在搜索框输入字符时,提示出与该字符有关的搜索项,如图:

自动补全.png

二、使用拼音分词

开源的拼音分词插件:Pinyin Analysis plugin

  • ① 下载解压

  • ② 上传到plugin目录/var/lib/docker/volumes/es-plugins/_data

查看elasticsearch的plugins目录位置,命令如下:

docker volume inspect es-plugins

显示结果:

[
    {
        "CreatedAt": "2022-04-04T17:07:34+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/es-plugins/_data",
        "Name": "es-plugins",
        "Options": null,
        "Scope": "local"
    }
]
plugins目录位置.png
  • ③ 重启elasticsearch
docker restart es

三、自定义分词器

1、分词器的组成

  • character filters:在tokenizer之前对文本进行处理,例如删除字符替换字符
  • tokenizer:将文本按照一定的规则切割成词条(term),例如keyword不分词、还有ik_smart
  • tokenizer filter:将tokenizer输出的词条做进一步处理,例如大小写转换同义词处理拼音处理等。
分词器的组成.png

2、使用自定义分词器

  • ① 直接使用的情形

如果直接使用分词器创建索引库,会创建大量的单字拼音索引,浪费空间,如下:

直接使用的情形.png
  • ② 配置后,同时使用自定义分词器创建倒排索引和搜索

使用pinyin分词器创建倒排索引,会导致shizi下同时存在狮子和虱子;此时,我们去搜素时,分词器又会分词出shizi,得到虱子的数据,不符合预期,如下:

同时使用自定义分词器创建倒排索引和搜索.png
不和预期产生原因.png
  • ③ 配合ik分词器配置后使用
# 自定义分词器
PUT /test 
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": { //自定义分词器
          "tokenizer": "ik_max_word", //先ik
          "filter": "py" //后py
        }
      },
      "filter": { //配置pinyin分词器
        "py": {
          "type": "pinyin",
          "keep_full_pinyin": false,
          "keep_joined_full_pinyin": true,
          "keep_original": true,
          "limit_first_letter_length": 16,
          "remove_duplicated_term": true,
          "none_chinese_pinyin_tokenize": false
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "my_analyzer",
        "search_analyzer": "ik_smart"
      }
    }
  }
}

四、ES自动补全

官方文档:ES completion suggester

1、completion suggester查询

ES提供了Completion Suggester查询来实现自动补全功能。这个查询会匹配以用户输入内容开头的词条并返回。

  • completion suggester查询的约束:
    Ⅰ 参与补全查询的字段必须是completion类型;
    Ⅱ 字段的内容一般是用来补全的多个词条形成的数组。

2、使用DSL语句进行查询

使用DSL语句进行查询.png

实例:

# 自动补全索引库
PUT /test2
{
  "mappings": {
    "properties": {
      "title": {
        "type": "completion"
      }
    }
  }
}

POST /test2/_doc
{
  "title": ["Sony", "WH-1000XM4"]
}
POST /test2/_doc
{
  "title": ["SK-II", "PITERA"]
}
POST /test2/_doc
{
  "title": ["Nintendo", "switch"]
}

GET /test2/_search
{
  "suggest": {
    "titleSuggest": {
      "text": "s", //查询的关键字
      "completion": {
        "field": "title", //补全查询的字段
        "skip_duplicates": true, //跳过重复数据
        "size": 10 //获取前10条结果
      }
    }
  }
}

3、RestClient实现自动补全

  • ① 准备DSL查询
// 1. 获取请求对象
SearchRequest request = new SearchRequest("hotel");

// 2. 准备DSL语句
request.source().suggest(new SuggestBuilder().addSuggestion(
        "hotelSuggest",
        SuggestBuilders.completionSuggestion("suggestion")
                .prefix("sh")
                .skipDuplicates(true)
                .size(10)
));

// 3. 发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
准备DSL查询.png
  • ② 解析结果数据
// 4. 解析响应
Suggest suggest = response.getSuggest();
// 4.1 根据补全查询名称,获取补全结果
CompletionSuggestion suggestions = suggest.getSuggestion("hotelSuggest");
// 4.2 获取options
List<CompletionSuggestion.Entry.Option> options = suggestions.getOptions();
// 4.3 遍历
for (CompletionSuggestion.Entry.Option option : options) {
    String text = option.getText().toString();

    // 5. 输出结果
    System.out.println(text);
}
解析结果数据.png

五、结尾

以上即为自动补全的全部内容,感谢阅读。