本篇文章主要介绍Elasticsearch搜索引擎之自动补全功能的介绍与使用。
以下正文开始
拼音分词器
当我们再很多网站输入拼音,关键字时,会出现商品,词语,与之有关联的的自动补全功能,可以帮助用户搜索到自己想要的结果。
Elasticsearch恰好能帮助我们完成这一业务。想要使用拼音来搜索商品,就需要使用拼音分词,根据字母做补全功能,就需要对文档按照拼音来分词。
首先我们需要安装拼音分词插件,将拼音分词插件下载到挂载的es-plugins目录下。下载完成后,我们可以测试一下是否可以,DSL代码如下:
POST /_analyze
{
"text": ["小威要向诸佬学习呀"],
"analyzer": "pinyin"
}
发送请求可以看到确实是按照拼音分词得到的结果,在创建索引库的时候可以以拼音分词的形式来创建:
自定义分词器
上面我们演示了使用拼音来做分词,但是上面是根据单个和组合的拼音来做分词的。在生产环境中,我们往往需要以拼音和汉字词语一起作为分词,这就需要我们来自定义分词器了。
elasticsearch中分词器(analyzer)的组成包含三部分:
- character filters:在tokenizer之前对文本进行处理。例如删除字符、替换字符
- tokenizer:将文本按照一定的规则切割成词条(term)。例如keyword,就是不分词;还有ik_smart
- tokenizer filter:将tokenizer输出的词条做进一步处理。例如大小写转换、同义词处理、拼音处理等
我们可以在创建索引库时,通过settings来配置自定义的分词器(analyzer):
// 自定义拼音分词器
PUT /test
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "ik_max_word",
"filter": "py"
}
},
"filter": { //自定义tokenizer filter
"py": { //过滤器名称
"type": "pinyin", //过滤器类型为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"//搜索使用ik分词器
}
}
}
}
在上面创建的索引库中放入两条文档:
{
"id": 1,
"name": "狮子"
}
POST /test/_doc/2
{
"id": 2,
"name": "虱子"
}
由于搜索时设置的根据ik_smart分词器进行分词,所以搜索结果只有狮子一条:
为了避免搜索到同音字,在创建索引库是时使用拼音分词器,在搜索时尽量不用。
completion suggester
es提供了completion suggester查询来实现自动补全功能,这个查询的概念就是匹配用户输入内容开头的词条并返回,对于文档中字段的类型,要遵循:参与补全查询的字段必须是completion类型;并且字段值是多个词条形成的数组。 举个栗子: 第一步,创建自动补全的索引库
# 创建自动补全的索引库
PUT test2
{
"mappings": {
"properties": {
"title":{
"type": "completion"
}
}
}
}
第二步,在创建的索引库中插入几条补全数据:
# 示例数据
POST test2/_doc
{
"title": ["Sony", "WH-1000XM3"]
}
POST test2/_doc
{
"title": ["SK-II", "PITERA"]
}
POST test2/_doc
{
"title": ["Nintendo", "switch"]
}
第三步,编写DSL语句,实现自动补全功能:
# 自动补全查询
POST /test/_search
{
"suggest": {
"title_suggest": {
"text": "s", // 搜索关键字s开头的数据
"completion": {
"field": "title", // 补全字段
"skip_duplicates": true, // 跳过重复的
"size": 10 // 获取前10条结果
}
}
}
}
执行上述的DSL语句,得到如下查询结果:
好了,本篇文章就先分享到这里了,后续会继续分享其他方面的知识,感谢大佬认真读完支持咯~