文章目录
-
-
- [1 前言](#1 前言)
- [2 Term Suggester](#2 Term Suggester)
-
- [2.1 基本介绍](#2.1 基本介绍)
- [2.2 使用 demo](#2.2 使用 demo)
- [2.3 常用参数](#2.3 常用参数)
-
- [2.3.1 suggest_mode](#2.3.1 suggest_mode)
- [2.3.2 max_edits](#2.3.2 max_edits)
- [2.3.3 prefix_length](#2.3.3 prefix_length)
- [2.3.4 min_word_length](#2.3.4 min_word_length)
- [3 Completion Suggester](#3 Completion Suggester)
-
- [3.1 基本描述](#3.1 基本描述)
- [3.2 基本使用](#3.2 基本使用)
- [3.3 查询参数](#3.3 查询参数)
-
- [3.3.1 size](#3.3.1 size)
- [3.3.2 skip_duplicates](#3.3.2 skip_duplicates)
- [3.3.3 fuzzy queries(模糊查询)](#3.3.3 fuzzy queries(模糊查询))
- [3.3.4 Regex queries(正则匹配)](#3.3.4 Regex queries(正则匹配))
- [4 结语](#4 结语)
-
1 前言
在上章介绍完 bool 查询后。我们接下来介绍搜索最常被使用的功能:搜索建议、搜索纠错。
在 ES 中的 Suggesters
API 中有以下 4 个 API
Term suggester
Phrase Suggester
Completion Suggester
Context Suggester
本文,因章幅原因,以及开发中使用频率,只选择讲解Term suggester
,Context Suggester
。更多内容请阅读 Suggesters API
2 Term Suggester
2.1 基本介绍
返回与输入的文本相似的 terms。在日常开发中,我们可以使用 term suggest 作为拼写纠错来使用。例如以下应用场景:
2.2 使用 demo
写入数据
POST test6/_doc
{
"intro": "apple fruits applz"
}
POST test6/_doc
{
"intro": "grapes fruit grapz"
}
POST test6/_doc
{
"intro": "banana fruit bannnn"
}
查询语法
GET test6/_search
{
"suggest": {
"my_suggest": { ①
"text": "banane", ②
"term": {
"field": "intro" ③
}
}
}
}
- ①:自定义的名词
- ②:用户输入的文本
- ③:被检索的字段
2.3 常用参数
2.3.1 suggest_mode
该参数有 3 个枚举值
- missing:如果用户输入的文本存在于文档中,则不推荐。适用于拼写检查
- popular:只推荐比用户输入的文本出现频率更高的 term。适用于推荐更流行的词
- always:无论用户输入的文本是否存在于文档中,都推荐。
love apples
会被分词为 love
, apples
,这 2 个词都不存在于文档中。ES 文档中有 apple
这个词,就推荐了。
GET test6/_search
{
"suggest": {
"my_suggest": {
"text": "love apples",
"term": {
"field": "intro",
"suggest_mode": "missing"
}
}
}
}
文档中存在 fruit
, fruits
。但是 fruit
出现的频率大于 fruits
因此 fruit
被推荐。
GET test6/_search
{
"suggest": {
"my_suggest": {
"text": "fruits",
"term": {
"field": "intro",
"suggest_mode": "popular"
}
}
}
}
不管文档中存不存在,ES 都会推荐。
GET test6/_search
{
"suggest": {
"my_suggest": {
"text": "applz",
"term": {
"field": "intro",
"suggest_mode": "always"
}
}
}
}
2.3.2 max_edits
最大编辑距离,可选值: 1~2,默认值 2。
什么是编辑距离,举个例子。
字符串 banane
变为 banana
的编辑距离为 1;
banzza
变为 banana
的编辑距离为 2;
即:需要修正多少个字符才能变为目标字符。
也就是说,使用 term suggest
至多允许错 2 个字母。
GET test6/_search
{
"suggest": {
"my_suggest": {
"text": "banane",
"term": {
"field": "intro",
"max_edits": 1
}
}
}
}
2.3.3 prefix_length
在返回的相似文本中,最小的公共前缀长度。默认值 1。
例如,输入文本 janana
,即使 ES 中存在 banana
的 term,banana
也不会被返回。因为 janana
的开头是 j
, banana
的开头是 b
,2 者没有公共前缀。
GET test6/_search
{
"suggest": {
"my_suggest": {
"text": "janana",
"term": {
"field": "intro",
"prefix_length": 0
}
}
}
}
2.3.4 min_word_length
用户输入的文本,被分词为 term 后,term 的长度必须大于 n,term 才会被推荐。n 默认值为 4。
例如:用户输入 grap apz
会被分词为 grap
, apz
2 个 term。apz
因为长度小于 4,因此不会被推荐。 grap
长度大于等于4,因此会被推荐。
GET test6/_search
{
"suggest": {
"my_suggest": {
"text": "grap apz",
"term": {
"field": "intro"
"string_distance": "ngram"
}
}
}
}
接下来,我们修改下 min_word_length
的值。则被建议 apple
, applz
GET test6/_search
{
"suggest": {
"my_suggest": {
"text": "app",
"term": {
"field": "intro",
"min_word_length": 3,
"suggest_mode": "missing",
"string_distance": "ngram"
}
}
}
}
需要注意:该 case
修改了 string_distance
参数。如果使用默认值 internal
则不会被建议。
PS:作者对算法不熟悉,因此不过多介绍 string_distance
可选的 5 个算法。更多内容见 term suggester 官网
3 Completion Suggester
3.1 基本描述
自动补全,或者搜索建议 API,一般常用在搜索框中。例如以下搜索场景。
该功能有非常快的响应速度,但是是以内存做为代价。下文是 ES 官网对其描述
The completion suggester provides auto-complete/search-as-you-type functionality. This is a navigational feature to guide users to relevant results as they are typing, improving search precision. It is not meant for spell correction or did-you-mean functionality like the term or phrase suggesters.
Ideally, auto-complete functionality should be as fast as a user types to provide instant feedback relevant to what a user has already typed in. Hence, completion suggester is optimized for speed. The suggester uses data structures that enable fast lookups, but are costly to build and are stored in-memory.
3.2 基本使用
设置 mapping
PUT test7
{
"mappings": {
"properties": {
"mysuggest": {
"type": "completion"
}
}
}
}
写入测试数据
POST test7/_doc
{
"mysuggest": "helloworld"
}
POST test7/_doc
{
"mysuggest": "hello java"
}
POST test7/_doc
{
"mysuggest": "hello"
}
POST test7/_doc
{
"mysuggest": "hello"
}
查询
GET test7/_search
{
"suggest": {
"mytest": {
"prefix": "he",
"completion": {
"field": "mysuggest"
}
}
}
}
3.3 查询参数
3.3.1 size
返回结果数量
GET test7/_search
{
"suggest": {
"mytest": {
"prefix": "he",
"completion": {
"field": "mysuggest"
"size": "1"
}
}
}
}
3.3.2 skip_duplicates
结果去重
GET test7/_search
{
"suggest": {
"mytest": {
"prefix": "he",
"completion": {
"field": "mysuggest",
"size": 5,
"skip_duplicates": true
}
}
}
}
3.3.3 fuzzy queries(模糊查询)
如果拼写有错误,也可以正常匹配结果
以下查询,是没有任何结果的,但是当我们使用 fuzzy queries
时,就允许有部分拼写错误
# 没有任何结果
POST test7/_search
{
"suggest": {
"mytest": {
"prefix": "hez",
"completion": {
"field": "mysuggest",
"skip_duplicates": true,
"size": 5
}
}
}
}
# 使用 `fuzzy queries`
POST test7/_search
{
"suggest": {
"mytest": {
"prefix": "hez",
"completion": {
"field": "mysuggest",
"fuzzy": {
"fuzziness": "auto"
},
"skip_duplicates": true,
"size": 5
}
}
}
}
fuzziness
参数可选值有:auto, 0,1,2。该参数的作用类似编辑距离。意思为允许拼写中错多少个字母。
当我们首字母拼写错误时,也想要有建议,则可以配置 prefix_length
参数,该参数默认为 1,意思为:必须满足的最小的公共前缀长度
POST test7/_search
{
"suggest": {
"mytest": {
"prefix": "zhe",
"completion": {
"field": "mysuggest",
"fuzzy": {
"fuzziness": 2,
"prefix_length": 0
},
"skip_duplicates": true,
"size": 5
}
}
}
}
当用户输入的文本长度为 1 时,我们也想要有建议,则可以修改 min_length
参数,该参数默认为 3,意思为:输入的文本长度最少为 3 时,才会建议
POST test7/_search
{
"suggest": {
"mytest": {
"prefix": "h",
"completion": {
"field": "mysuggest",
"fuzzy": {
"fuzziness": 2,
"min_length":1
},
"skip_duplicates": true,
"size": 5
}
}
}
}
3.3.4 Regex queries(正则匹配)
实际开发比较少用,不过多介绍
GET test7/_search
{
"suggest": {
"mytest": {
"regex": "h.*o",
"completion": {
"field": "mysuggest",
"skip_duplicates": true,
"size": 5
}
}
}
}
4 结语
我们已经将 ES 大部分主流的查询介绍完了,下一个篇章我们将介绍 ES 的分词器。