Elasticsearch 7.x 深入【8】Suggester

2020-05-25  本文已影响0人  孙瑞锴

1. 借鉴

极客时间 阮一鸣老师的Elasticsearch核心技术与实战
Elasticsearch 5.x Suggester详解
店名大全 -_-||
官方文档 search-suggesters
详解编辑距离(Edit Distance)及其代码实现
Edit Distance 算法实现及其设计原理
leetcode edit-distance
elasticsearch suggest实现搜索词自动补全
Elasticsearch之建议器suggester
Elasticsearch搜索Suggest功能优化
【Elasticsearch】7.2 自动补全、纠错、拼音搜索
elasticsearch使用more_like_this实现基于内容的推荐
Field datatypes(2)
elasticsearch补全功能之只补全筛选后的部分数据context suggester
Elasticsearch学习笔记5: suggest实现搜索补全
Phrase Suggester
lucene底层数据结构——FST,针对field使用列存储,delta encode压缩doc ids数组,LZ4压缩算法
关于Lucene的词典FST深入剖析
FST
Completion Suggester.md

2. 开始

Suggester,顾名思义,即用户输入后,进行自动补全或者纠错,并给出相应的结果。
其原理是将输入分解为token,然后再索引中查找相似的关键词(term)并返回
在es里面有四种Suggester:

我们逐一来看下

数据准备:使用到的数据请看这里<Elasticsearch 7.x 深入 数据准备>

Term Suggester

The term suggester suggests terms based on edit distance. The provided suggest text 
is analyzed before terms are suggested. The suggested terms are provided per 
analyzed suggest text token. The term suggester doesn’t take the query into account 
that is part of request.

term suggester基于编辑距离算法实现。在提供建议之前,对输入的文本进行分析。

我们在索引中有一个“三生石工艺坊批发店”这个店铺,我们基于这个来查询。

GET /store_suggest/_analyze
{
  "analyzer": "ik_smart",
  "text": ["三生石工艺坊批发店"]
}
{
  "tokens" : [
    { "token" : "三生石", },
    { "token" : "工艺", },
    { "token" : "坊", },
    { "token" : "批发店", }
  ]
}
GET /store_suggest/_search
{
  "suggest": {
    "term-suggestion": {
      "text": "三声石", // 我们输入的内容
      "term": {
        "field": "name", // 指定哪个字段
        "suggest_mode": "missing", // 参数1
        "min_word_length": 2 // 参数2
      }
    }
  }
}
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "suggest" : {
    "term-suggestion" : [
      {
        "text" : "三声",
        "offset" : 0,
        "length" : 2,
        "options" : [
          {
            "text" : "三生",
            "score" : 0.5,
            "freq" : 1
          }
        ]
      },
      {
        "text" : "石",
        "offset" : 2,
        "length" : 1,
        "options" : [ ]
      }
    ]
  }
}
字段名称 解释 默认值
text      输入内容 -
field 作用的字段 -
analyzer 使用的分词器 search analyzer
size 使用的分词器 每个建议文本返回的最大提示数量
sort 如何排序:
score:首先按分数排序,然后按文档频率排序,最后按关键词本身排序。
frequency:首先按文档频率排序,然后是相似度评分,最后是关键词本身。
-
suggest_mode 模式:
missing:如果索引中已经存在,就不提供建议
popular:推荐出现频率更高的词
always:无论是否存在,都提供建议
-
字段名称 解释 默认值
max_edits                                               编辑距离:只能是1和2之间的值。任何其他值都会导致抛出错误的请求。 -2             
prefix_length 必须匹配的最小前缀字符的数量。 1
min_word_length 建议的文本术语必须具有的最小长度才能被包括在内。 4
string_distance 要使用哪个字符串距离实现来比较建议的term的相似性
internal:默认值,基于damerau_levenshtein,对于比较索引内的词的字符串距离进行了高度优化
damerau_levenshtein:基于Damerau-Levenshtein算法
levenshtein:基于Levenshtein edit distance算法
jaro_winkler:基于Jaro-Winkler算法
ngram: 基于character n-grams算法
internal
shard_size 设置要从每个分片中检索的建议的最大数量。在reduce阶段,只根据size选项返回前N个建议。默认size选项,将这个值设置为大于size的值,这有助于获得更准确的文档频率,以牺牲性能为代价获得拼写更准确。由于term是在分词时产生的,因此分片级的文档中拼写正确的频率可能并不精确。增加这值将使这些文件频率更精确。 -
max_inspections 一个因子,用于与shards_size相乘,以便检查shard级别上的更多候选拼写更正。以牺牲性能为代价来提高精度。 5
min_doc_freq 建议中出现的文档数量的最小阈值。这可以指定为绝对数量,也可以指定为文档数量的相对百分比。这可以通过只建议高词频的term来提高质量。默认为0f,未启用。如果指定的值大于1,则该数字不能是小数。这个选项使用分片级文档频率。 0f
max_term_freq 建议文本标记可以存在的文档数量的最大阈值,以便将其包括在内。可以是表示文档频率的相对百分比数(例如0.4)或绝对数。如果指定的值大于1,则不能指定分数。这可以用来排除高频术语(通常拼写正确)的拼写检查。这也提高了拼写检查的性能。这个选项使用碎片级文档频率。 0.01

Phrase Suggester

The phrase suggester adds additional logic on top of the term suggester to select entire 
corrected phrases instead of individual tokens weighted based on ngram-language 
models. In practice this suggester will be able to make better decisions about which 
tokens to pick based on co-occurrence and frequencies.

phrase suggester 在 term suggester 之上添加额外的逻辑以选择整个经校正的短语,而不是基于 ngram-language 模型加权的单个 token 。

GET /store_suggest/_search
{
  "suggest": {
    "phrase-suggestion": {
      "text": "三生时工艺坊批发店",
      "phrase": {
        "field": "name",
        "max_errors": 4,
        "confidence": 0,
        "direct_generator": [{
          "field": "name",
          "suggest_mode": "missing"
        }],
        "highlight": {
          "pre_tag": "<em style='color=\"red\">",
          "post_tag": "</em>"
        }
      }
    }
  }
}
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "suggest" : {
    "phrase-suggestion" : [
      {
        "text" : "三生时工艺坊批发店",
        "offset" : 0,
        "length" : 9,
        "options" : [
          {
            "text" : "三生 时 工艺 坊 批发店",
            "highlighted" : "三生 时 工艺 坊 批发店",
            "score" : 3.0157945E-4
          }
        ]
      }
    ]
  }
}
字段名称 解释 默认值
field                                      作用的字段 -
gram_size -
real_word_error_likelihood 一个词被拼错的可能性,即使这个词存在于字典中。默认值是0.95,这意味着有5%的单词是拼写错误的。 0.95
confidence 限制返回结果 1
max_errors 最多可以拼接错误的term数量 -
separator 用于在双字母字段中分隔term的分隔符。如果未设置,空白字符将用作分隔符。 空字符
size 为每个查询项生成的候选项数 5
analyzer -
shard_size 设置要从每个分片检索的建议术语的最大数量。在reduce阶段,只根据size选项返回前N个建议。默认为5。 5
text 设置要进行建议的文本 -
highlight 高亮,pre_tag和post_tag -
collate 根据指定的查询检查每个建议,以删除索引中不存在匹配文档的建议。 -
direct_generator 直接生成器 -
字段名称 解释 默认值
field                                              从中获取候选 suggestions 的字段。 这是必需的选项,需要设置全局或每个 suggestion 。 -
size 每个 suggestion 文本标记返回的最大更正值。 -
max_edits 最大编辑距离候选 suggestions 可以具有,以便被认为是 suggestion 。 只能是介于1和2之间的值。任何其他值都会导致抛出错误的请求错误。 2
prefix_length 必须匹配的最小前缀字符的数量是候选 suggestions 。 增加此数字可提高拼写检查性能。 通常拼写错误不会出现在术语的开头。 1
min_word_length suggest 文本术语必须包含的最小长度。 4
max_inspections 用于乘以 shards_size 以便在碎片级别上检查更多候选拼写校正的因子。 可以以性能为代价提高精度。 5
min_doc_freq suggestion 应该出现的文档数量的最小阈值。这可以指定为绝对数字或文档数量的相对百分比。 这可以通过仅提示高频项来提高质量。 如果指定的值大于1,则该数字不能为小数。 分片级文档频率用于此选项。 默认值为0f,未启用。
max_term_freq suggestion 文本标记可以存在的文档数量中的最大阈值,以便包括。 可以是表示文档频率的相对百分比数字(例如0.4)或绝对数字。 如果指定的值大于1,则不能指定小数。 这可以用于排除高频术语的拼写检查。 高频项通常拼写正确,这也提高了拼写检查的性能。 分片级文档频率用于此选项。 0.01f
pre_filter 应用于传递到该候选生成器的每个令牌的过滤器(分析器)。 在生成候选项之前,此过滤器应用于原始令牌。 -
post_filter 在它们被传递给实际短语记分器之前应用于每个生成的令牌的过滤器(分析器)。 -

Completion Suggester

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.

大意是:只能基于前缀查询,速度很快,性能要求高
需求场景是:每输入一个字符,即时发送一个请求查询匹配项
数据结构:并非是倒排索引实现的,而是将分词的数据编码成FST和索引一起存放;FST会被加载进内存,速度很快

使用Completion是有限制的,即在指定映射的时候,需要指定类型为completion,我们来个栗子,mapping信息可查看数据准备。

GET /store_suggest_v2/_search
{
  "suggest": {
    "completion-suggestion": {
      "prefix": "三生",
      "completion": {
        "field": "name_suggest"
      }
    }
  }
}
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "suggest" : {
    "completion-suggestion" : [
      {
        "text" : "三生",
        "offset" : 0,
        "length" : 2,
        "options" : [
          {
            "text" : "三生石工艺坊批发店",
            "_index" : "store_suggest_v2",
            "_type" : "_doc",
            "_id" : "jSJHQXIBmZ523HCO5Ixv",
            "_score" : 1.0,
            "_source" : {
              "name" : "三生石工艺坊批发店",
              "name_suggest" : "三生石工艺坊批发店"
            }
          }
        ]
      }
    ]
  }
}
GET /store_suggest_v2/_search
{
  "suggest": {
    "completion-suggestion": {
      "prefix": "工艺",
      "completion": {
        "field": "name_suggest"
      }
    }
  }
}
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "suggest" : {
    "completion-suggestion" : [
      {
        "text" : "工艺",
        "offset" : 0,
        "length" : 2,
        "options" : [ ]
      }
    ]
  }
}

fuzzy

当前前缀归前缀,你后缀拼错了它也可以支持的,我们来看下completion的模糊属性fuzzy

GET /store_suggest_v2/_search
{
  "suggest": {
    "completion-suggestion": {
      "prefix": "三生是",
      "completion": {
        "field": "name_suggest",
        "fuzzy" : {
          "fuzziness" : 2,
           "unicode_aware": true
        }
      }
    }
  }
}
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "suggest" : {
    "completion-suggestion" : [
      {
        "text" : "三生是",
        "offset" : 0,
        "length" : 3,
        "options" : [
          {
            "text" : "三生石工艺坊批发店",
            "_index" : "store_suggest_v2",
            "_type" : "_doc",
            "_id" : "jSJHQXIBmZ523HCO5Ixv",
            "_score" : 1.0,
            "_source" : {
              "name" : "三生石工艺坊批发店",
              "name_suggest" : "三生石工艺坊批发店"
            }
          }
        ]
      }
    ]
  }
}

我们看下fuzzy可以配置的参数:

字段名称 解释 默认值
fuzziness 模糊因子:在查询文本或关键字字段时,模糊性被解释为Levenshtein编辑距离——需要对一个字符串进行的字符更改数,以使其与另一个字符串相同。 AUTO
transpositions 如果设置为true,换位被记为一次更改而不是两次 true
min_length 模糊建议器返回前输入的最小长度 3
prefix_length 输入的最小长度(未针对模糊替代项进行检查) 1
unicode_aware 如果设置为true,则所有的度量都以unicode代码点而不是字节为单位。这比原始字节稍慢,因此默认情况下设置为false。 false

regex

其实completion也是支持正则查询的,但是我查了很多资料,都是英文正则的例子,我自己测试中文没有成功,我感觉也应该在这则这里加一个unicode_aware属性,它应该也是按照字节来算的,我将测试的例子,写在下面,希望有跟多见解的看官能给我提示。// TODO

GET /store_suggest_v2/_search
{
  "suggest": {
    "completion-suggestion": {
      "regex": "三生.*?",
      "completion": {
        "field": "name_suggest"
      }
    }
  }
}

Context Suggester

The completion suggester considers all documents in the index, but it is often desirable to 
serve suggestions filtered and/or boosted by some criteria. 

大意是:可以通过筛选提供建议。
context 支持两种类型,分别是category(任意字符串),geo(地理位置信息)。数据信息可查看数据准备

PUT /store_suggest_v3
{
  "mappings": {
    "properties": {
      "name": {
      "type": "text",
      "analyzer": "ik_max_word"
      },
      "name_suggest": {
        "type": "completion",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart",
        "contexts": [{
          "type": "category",
          "name": "scene"
        }]
      }
    }
  }
}

我们查询“意美”,但是有两个“意美”开头的店铺,但是这两个的性质是不一样的,一个是首饰店铺,一个是家具店铺,我们可以根据用户的场景来选择

# 目前场景是饰品,我们使用的上下文属性值是ornament,如果场景是家具,那我们就使用furniture
GET /store_suggest_v3/_search
{
  "suggest": {
    "name_suggest": {
      "prefix": "意美",
      "completion": {
        "field": "name_suggest",
        "contexts": {
          "scene": "ornament"
        }
      }
    }
  }
}
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "suggest" : {
    "name_suggest" : [
      {
        "text" : "意美",
        "offset" : 0,
        "length" : 2,
        "options" : [
          {
            "text" : "意美家居饰品",
            "_index" : "store_suggest_v3",
            "_type" : "_doc",
            "_id" : "yAxiS3IBSI7tvzqGolz1",
            "_score" : 1.0,
            "_source" : {
              "name" : "意美家居饰品",
              "name_suggest" : {
                "input" : [
                  "意美家居饰品"
                ],
                "contexts" : {
                  "scene" : "ornament"
                }
              }
            },
            "contexts" : {
              "scene" : [
                "ornament"
              ]
            }
          }
        ]
      }
    ]
  }
}

3. 大功告成

上一篇 下一篇

猜你喜欢

热点阅读