一 序
本文属于极客时间Elasticsearch核心技术与实战学习笔记系列。
二 什么是搜索建议
- 现代的搜索引擎,一般都会提供 Suggest as you type 的功能
- 帮助用户在输入搜索的过程中,进行自动补全或者纠错。通过协助用户输入更加精准的关键词,提高后续搜索阶段文档匹配的程度
- 在 google 上搜索,一开始会自动补全。当输入到一定长度,如因为单词拼写错误无法补全,就会开始提示相似的词或者句子
2.1 Elasticsearch Suggester API
- 搜索引擎中类似的功能,在 ES 中通过 Sugester API 实现的
- 原理:将输入的文档分解为 Token,然后在索引的字段里查找相似的 Term 并返回
- 根据不同的使用场景,ES 设计了 4 种类别的 Suggesters
- Term Suggester(纠错补全,输入错误的情况下补全正确的单词)
- Phrase Suggester(自动补全短语,输入一个单词补全整个短语)
- Completion Suggester(完成补全单词,输出如前半部分,补全整个单词)
- Context Suggester(上下文补全)
2.2Term Suggester
demo:
数据准备
DELETE articles
PUT articles
{
"mappings": {
"properties": {
"title_completion":{
"type": "completion"
}
}
}
}
POST articles/_bulk
{ "index" : { } }
{ "title_completion": "lucene is very cool"}
{ "index" : { } }
{ "title_completion": "Elasticsearch builds on top of lucene"}
{ "index" : { } }
{ "title_completion": "Elasticsearch rocks"}
{ "index" : { } }
{ "title_completion": "elastic is the company behind ELK stack"}
{ "index" : { } }
{ "title_completion": "Elk stack rocks"}
{ "index" : {} }
"suggest" : {
"term-suggestion" : [
{
"text" : "lucen",
"offset" : 0,
"length" : 5,
"options" : [
{
"text" : "lucene",
"score" : 0.8,
"freq" : 2
}
]
},
{
"text" : "rock",
"offset" : 6,
"length" : 4,
"options" : [ ]
}
]
}
搜索 “lucen rock”:看结果: "lucene",//推荐了,而rock 没有推荐。
搜索 “lucen rock”:
- 每个建议都包含了一个算分,相似性是通过 Levenshtein Edit Distance 的算法实现的。核心思想就是一个词改动多少字段就可以和另外一个词一致。提供了很多可选参数来控制相似性的模糊程度。
几种 Suggestion Mode
- Missing - 如索引中已存在,就不提供建议
- Popular - 推荐出现频率更加高的词
- Always - 无论是否存在,都提供建议
因为文档里有两条rocks,所以认为popular的结果为rocks. 换成always也是一样的结果。
POST /articles/_search
{
"suggest": {
"term-suggestion": {
"text": "lucen rock",
"term": {
"suggest_mode": "always",
"field": "body"
}
}
}
}
如果换成hocks查询:
返回:‘
"suggest" : {
"term-suggestion" : [
{
"text" : "lucen",
"offset" : 0,
"length" : 5,
"options" : [
{
"text" : "lucene",
"score" : 0.8,
"freq" : 2
}
]
},
{
"text" : "hocks",
"offset" : 6,
"length" : 5,
"options" : [ ]
}
]
}
}
这里有一些相关的参数可以设置,
lowercase_terms
:表示在文本分析后,将推荐文本术语转换成小写;max_edits
:表示可以被选为建议的edit distance的最大值,只能是1和2之前的数值,默认是2;prefix_length
:表示可以被选为建议的最小前缀字符的长度,默认为1,增加这个长度可以提高拼写检查的性能,通常拼写错误不会发生在术语的最前面(prefix_len
参数已经丢弃);min_word_length
:表示推荐文本的最小产嘀咕,默认为4(min_word_len
参数已被丢弃);shard_size
:表示从每个独立碎片(分片)获取建议的最大数量,在减少阶段(reduce phase)基于size
参数的设置只返回前N个建议,默认就是size
提供的值,将shard_size
设置为大于size
参数,可能对得到性能为代价更准确的文档频率拼写纠正更加有效,因为术语分区中碎片,碎片级别文档频率的拼写纠正可能不准确,增加这将使这些文档频率更精确;max_inspections
:表示一个因子,这个参数和shard_size
参数相乘以便在碎片级别检查更多的候选者的拼写错误,可以提高以性能为代价的准确性,参数默认为5;min_doc_freq
:表示一个建议中应包含文档数目的最小限制,可以指定为一个确切的数或文档数的相对百分比,可以通过推荐高频术语来提高质量,min_doc_freq
默认是0(即不开启此功能),如果将这个参数指定为一个大于1的值(不能是小数,只是大于1时不能指定为小数),碎片级别的文档频率用于这个选项;max_term_freq
:表示推荐文本可以包含的文档数目的最大限制,可以是一个代表文档频率的确切值,也可以是一个相对百分数(比如0.4),如果指定为一个大于1的数(不可以指定为小数),默认是0.01f,这个参数可以用来排除高频术语的拼写检查,高频术语通常在前几个字符是拼写正确的以提高拼写检查的性能,碎片(分片)性能文档频率用于这个选项;string_distance
:表示一个字符串距离用于和推荐内容相比它们之间的相似性,这个参数可能的值有5个:
internal
:表示默认的基于damerau_levenshtein算法,但在比较字符串距离内的索引已经做过高度优化;damerau_levenshtein
:是一种基于Damerau-Levenshtein算法的字符串距离算法;levenshtein
:是一种基于Levenshtein edit distance算法的字符串距离算法;jaro_winkler
:是一种基于Jaro-Winkler算法的字符串距离算法;ngram
:是一种基于字符连词的字符串距离算法;
针对上面hocks的case:可以使用prefix_length调整最小前缀的长度
2.3 Phrase Suggester
修改下:confidence
将输入的文本分解为Token,然后再索引的字典里查找相似的term 并返回 .
实际应用中应该有优化空间吧。