建议器
编辑建议器
编辑使用建议器,根据提供的文本建议外观相似的术语。
resp = client.search( index="my-index-000001", query={ "match": { "message": "tring out Elasticsearch" } }, suggest={ "my-suggestion": { "text": "tring out Elasticsearch", "term": { "field": "message" } } }, ) print(resp)
response = client.search( index: 'my-index-000001', body: { query: { match: { message: 'tring out Elasticsearch' } }, suggest: { "my-suggestion": { text: 'tring out Elasticsearch', term: { field: 'message' } } } } ) puts response
const response = await client.search({ index: "my-index-000001", query: { match: { message: "tring out Elasticsearch", }, }, suggest: { "my-suggestion": { text: "tring out Elasticsearch", term: { field: "message", }, }, }, }); console.log(response);
POST my-index-000001/_search { "query" : { "match": { "message": "tring out Elasticsearch" } }, "suggest" : { "my-suggestion" : { "text" : "tring out Elasticsearch", "term" : { "field" : "message" } } } }
请求
编辑建议功能通过使用建议器,根据提供的文本建议外观相似的术语。建议请求部分与 _search
请求中的查询部分一起定义。如果省略查询部分,则只返回建议。
示例
编辑每个请求可以指定多个建议。每个建议都用任意名称标识。在下面的示例中,请求了两个建议。 my-suggest-1
和 my-suggest-2
建议都使用 term
建议器,但具有不同的 text
。
resp = client.search( suggest={ "my-suggest-1": { "text": "tring out Elasticsearch", "term": { "field": "message" } }, "my-suggest-2": { "text": "kmichy", "term": { "field": "user.id" } } }, ) print(resp)
response = client.search( body: { suggest: { "my-suggest-1": { text: 'tring out Elasticsearch', term: { field: 'message' } }, "my-suggest-2": { text: 'kmichy', term: { field: 'user.id' } } } } ) puts response
const response = await client.search({ suggest: { "my-suggest-1": { text: "tring out Elasticsearch", term: { field: "message", }, }, "my-suggest-2": { text: "kmichy", term: { field: "user.id", }, }, }, }); console.log(response);
POST _search { "suggest": { "my-suggest-1" : { "text" : "tring out Elasticsearch", "term" : { "field" : "message" } }, "my-suggest-2" : { "text" : "kmichy", "term" : { "field" : "user.id" } } } }
下面的建议响应示例包括 my-suggest-1
和 my-suggest-2
的建议响应。每个建议部分都包含条目。每个条目实际上是建议文本中的一个标记,并包含建议条目文本、建议文本中的原始起始偏移量和长度,以及如果找到的任意数量的选项。
{ "_shards": ... "hits": ... "took": 2, "timed_out": false, "suggest": { "my-suggest-1": [ { "text": "tring", "offset": 0, "length": 5, "options": [ {"text": "trying", "score": 0.8, "freq": 1 } ] }, { "text": "out", "offset": 6, "length": 3, "options": [] }, { "text": "elasticsearch", "offset": 10, "length": 13, "options": [] } ], "my-suggest-2": ... } }
每个选项数组都包含一个选项对象,该对象包含建议的文本、其文档频率以及与建议条目文本相比的分数。分数的含义取决于所使用的建议器。词项建议器的分数基于编辑距离。
全局建议文本
编辑为了避免重复建议文本,可以定义一个全局文本。在下面的示例中,建议文本是全局定义的,并适用于 my-suggest-1
和 my-suggest-2
建议。
$params = [ 'body' => [ 'suggest' => [ 'text' => 'tring out Elasticsearch', 'my-suggest-1' => [ 'term' => [ 'field' => 'message', ], ], 'my-suggest-2' => [ 'term' => [ 'field' => 'user', ], ], ], ], ]; $response = $client->search($params);
resp = client.search( suggest={ "text": "tring out Elasticsearch", "my-suggest-1": { "term": { "field": "message" } }, "my-suggest-2": { "term": { "field": "user" } } }, ) print(resp)
response = client.search( body: { suggest: { text: 'tring out Elasticsearch', "my-suggest-1": { term: { field: 'message' } }, "my-suggest-2": { term: { field: 'user' } } } } ) puts response
res, err := es.Search( es.Search.WithBody(strings.NewReader(`{ "suggest": { "text": "tring out Elasticsearch", "my-suggest-1": { "term": { "field": "message" } }, "my-suggest-2": { "term": { "field": "user" } } } }`)), es.Search.WithPretty(), ) fmt.Println(res, err)
const response = await client.search({ suggest: { text: "tring out Elasticsearch", "my-suggest-1": { term: { field: "message", }, }, "my-suggest-2": { term: { field: "user", }, }, }, }); console.log(response);
POST _search { "suggest": { "text" : "tring out Elasticsearch", "my-suggest-1" : { "term" : { "field" : "message" } }, "my-suggest-2" : { "term" : { "field" : "user" } } } }
在上面的示例中,建议文本也可以指定为特定于建议的选项。在建议级别指定的建议文本将覆盖全局级别的建议文本。
词项建议器
编辑term
建议器根据编辑距离建议词项。提供的建议文本在建议词项之前进行分析。每个分析后的建议文本标记都提供建议的词项。term
建议器不考虑作为请求一部分的查询。
通用建议选项
编辑
|
建议文本。建议文本是必须全局或按建议设置的必需选项。 |
|
从中获取候选建议的字段。这是一个必需选项,需要全局或按建议设置。 |
|
用于分析建议文本的分析器。默认为建议字段的搜索分析器。 |
|
每个建议文本标记返回的最大更正数。 |
|
定义如何按建议文本词项对建议进行排序。两个可能的值
|
|
建议模式控制包含哪些建议,或者控制为哪些建议文本词项建议建议。可以指定三个可能的值
|
其他词项建议选项
编辑
|
候选建议被视为建议的最大编辑距离。只能是 1 到 2 之间的值。任何其他值都会导致抛出错误请求错误。默认为 2。 |
|
为了成为建议的候选者,必须匹配的最小前缀字符数。默认为 1。增加此数字会提高拼写检查性能。通常,拼写错误不会出现在词项的开头。 |
|
为了包含在内,建议文本词项必须具有的最小长度。默认为 |
|
设置从每个单独分片检索的最大建议数。在缩减阶段,仅根据 |
|
用于与 |
|
建议应出现在其中的文档数量的最小阈值。这可以指定为文档绝对数量或相对百分比。这可以通过仅建议高频词项来提高质量。默认为 0f,并且未启用。如果指定的值大于 1,则该数字不能是小数。此选项使用分片级文档频率。 |
|
为了包含在内,建议文本标记可以存在的最大文档数量阈值。可以是相对百分比数字(例如,0.4)或表示文档频率的绝对数字。如果指定的值大于 1,则不能指定小数。默认为 0.01f。这可用于排除高频词项(通常拼写正确),以免被拼写检查。这也提高了拼写检查性能。此选项使用分片级文档频率。 |
|
用于比较建议的词项相似程度的字符串距离实现。可以指定五个可能的值
|
短语建议器
编辑term
建议器提供了一个非常方便的 API,用于在特定字符串距离内按每个标记访问单词替代项。该 API 允许单独访问流中的每个标记,而建议选择则留给 API 使用者。但是,通常需要预先选择的建议才能呈现给最终用户。phrase
建议器在 term
建议器的基础上添加了额外的逻辑,以选择整个更正的短语,而不是基于 ngram-language
模型加权的单个标记。实际上,此建议器将能够根据共现和频率更好地决定选择哪些标记。
API 示例
编辑通常,phrase
建议器需要预先进行特殊映射才能工作。此页面上的 phrase
建议器示例需要以下映射才能工作。reverse
分析器仅在最后一个示例中使用。
resp = client.indices.create( index="test", settings={ "index": { "number_of_shards": 1, "analysis": { "analyzer": { "trigram": { "type": "custom", "tokenizer": "standard", "filter": [ "lowercase", "shingle" ] }, "reverse": { "type": "custom", "tokenizer": "standard", "filter": [ "lowercase", "reverse" ] } }, "filter": { "shingle": { "type": "shingle", "min_shingle_size": 2, "max_shingle_size": 3 } } } } }, mappings={ "properties": { "title": { "type": "text", "fields": { "trigram": { "type": "text", "analyzer": "trigram" }, "reverse": { "type": "text", "analyzer": "reverse" } } } } }, ) print(resp) resp1 = client.index( index="test", refresh=True, document={ "title": "noble warriors" }, ) print(resp1) resp2 = client.index( index="test", refresh=True, document={ "title": "nobel prize" }, ) print(resp2)
response = client.indices.create( index: 'test', body: { settings: { index: { number_of_shards: 1, analysis: { analyzer: { trigram: { type: 'custom', tokenizer: 'standard', filter: [ 'lowercase', 'shingle' ] }, reverse: { type: 'custom', tokenizer: 'standard', filter: [ 'lowercase', 'reverse' ] } }, filter: { shingle: { type: 'shingle', min_shingle_size: 2, max_shingle_size: 3 } } } } }, mappings: { properties: { title: { type: 'text', fields: { trigram: { type: 'text', analyzer: 'trigram' }, reverse: { type: 'text', analyzer: 'reverse' } } } } } } ) puts response response = client.index( index: 'test', refresh: true, body: { title: 'noble warriors' } ) puts response response = client.index( index: 'test', refresh: true, body: { title: 'nobel prize' } ) puts response
const response = await client.indices.create({ index: "test", settings: { index: { number_of_shards: 1, analysis: { analyzer: { trigram: { type: "custom", tokenizer: "standard", filter: ["lowercase", "shingle"], }, reverse: { type: "custom", tokenizer: "standard", filter: ["lowercase", "reverse"], }, }, filter: { shingle: { type: "shingle", min_shingle_size: 2, max_shingle_size: 3, }, }, }, }, }, mappings: { properties: { title: { type: "text", fields: { trigram: { type: "text", analyzer: "trigram", }, reverse: { type: "text", analyzer: "reverse", }, }, }, }, }, }); console.log(response); const response1 = await client.index({ index: "test", refresh: "true", document: { title: "noble warriors", }, }); console.log(response1); const response2 = await client.index({ index: "test", refresh: "true", document: { title: "nobel prize", }, }); console.log(response2);
PUT test { "settings": { "index": { "number_of_shards": 1, "analysis": { "analyzer": { "trigram": { "type": "custom", "tokenizer": "standard", "filter": ["lowercase","shingle"] }, "reverse": { "type": "custom", "tokenizer": "standard", "filter": ["lowercase","reverse"] } }, "filter": { "shingle": { "type": "shingle", "min_shingle_size": 2, "max_shingle_size": 3 } } } } }, "mappings": { "properties": { "title": { "type": "text", "fields": { "trigram": { "type": "text", "analyzer": "trigram" }, "reverse": { "type": "text", "analyzer": "reverse" } } } } } } POST test/_doc?refresh=true {"title": "noble warriors"} POST test/_doc?refresh=true {"title": "nobel prize"}
设置好分析器和映射后,可以在使用 term
建议器的相同位置使用 phrase
建议器
resp = client.search( index="test", suggest={ "text": "noble prize", "simple_phrase": { "phrase": { "field": "title.trigram", "size": 1, "gram_size": 3, "direct_generator": [ { "field": "title.trigram", "suggest_mode": "always" } ], "highlight": { "pre_tag": "<em>", "post_tag": "</em>" } } } }, ) print(resp)
const response = await client.search({ index: "test", suggest: { text: "noble prize", simple_phrase: { phrase: { field: "title.trigram", size: 1, gram_size: 3, direct_generator: [ { field: "title.trigram", suggest_mode: "always", }, ], highlight: { pre_tag: "<em>", post_tag: "</em>", }, }, }, }, }); console.log(response);
POST test/_search { "suggest": { "text": "noble prize", "simple_phrase": { "phrase": { "field": "title.trigram", "size": 1, "gram_size": 3, "direct_generator": [ { "field": "title.trigram", "suggest_mode": "always" } ], "highlight": { "pre_tag": "<em>", "post_tag": "</em>" } } } } }
该响应包含按最可能的拼写更正分数排序的建议。在这种情况下,我们收到了预期的更正“诺贝尔奖”。
{ "_shards": ... "hits": ... "timed_out": false, "took": 3, "suggest": { "simple_phrase" : [ { "text" : "noble prize", "offset" : 0, "length" : 11, "options" : [ { "text" : "nobel prize", "highlighted": "<em>nobel</em> prize", "score" : 0.48614594 }] } ] } }
基本短语建议 API 参数
编辑
|
用于对语言模型进行 n-gram 查找的字段的名称,建议器将使用此字段来获取统计信息以对更正进行评分。此字段是强制性的。 |
|
设置 |
|
即使该词项存在于字典中,该词项拼写错误的概率。默认值为 |
|
置信度级别定义一个应用于输入短语分数的因子,该因子用作其他建议候选者的阈值。只有得分高于阈值的候选者才会包含在结果中。例如,置信度级别为 |
|
为了形成更正,被视为拼写错误的词项的最大百分比。此方法接受范围 |
|
用于分隔双字母组字段中词项的分隔符。如果未设置,则将空格字符用作分隔符。 |
|
为每个单独的查询词项生成的候选者数量。像 |
|
设置用于分析建议文本的分析器。默认为通过 |
|
设置从每个单独分片检索的最大建议词项数。在缩减阶段,仅根据 |
|
设置要为其提供建议的文本/查询。 |
|
设置建议高亮显示。如果未提供,则不返回 |
|
针对指定的 |
resp = client.search( index="test", suggest={ "text": "noble prize", "simple_phrase": { "phrase": { "field": "title.trigram", "size": 1, "direct_generator": [ { "field": "title.trigram", "suggest_mode": "always", "min_word_length": 1 } ], "collate": { "query": { "source": { "match": { "{{field_name}}": "{{suggestion}}" } } }, "params": { "field_name": "title" }, "prune": True } } } }, ) print(resp)
const response = await client.search({ index: "test", suggest: { text: "noble prize", simple_phrase: { phrase: { field: "title.trigram", size: 1, direct_generator: [ { field: "title.trigram", suggest_mode: "always", min_word_length: 1, }, ], collate: { query: { source: { match: { "{{field_name}}": "{{suggestion}}", }, }, }, params: { field_name: "title", }, prune: true, }, }, }, }, }); console.log(response);
POST test/_search { "suggest": { "text" : "noble prize", "simple_phrase" : { "phrase" : { "field" : "title.trigram", "size" : 1, "direct_generator" : [ { "field" : "title.trigram", "suggest_mode" : "always", "min_word_length" : 1 } ], "collate": { "query": { "source" : { "match": { "{{field_name}}" : "{{suggestion}}" } } }, "params": {"field_name" : "title"}, "prune": true } } } } }
平滑模型
编辑phrase
建议器支持多种平滑模型,以平衡不频繁的 grams(索引中不存在的 grams(shingles))和频繁的 grams(在索引中至少出现一次)之间的权重。可以通过将 smoothing
参数设置为以下选项之一来选择平滑模型。每个平滑模型都支持可以配置的特定属性。
|
一个简单的回退模型,如果较高阶 n-gram 模型的计数为 |
|
一个使用加性平滑的平滑模型,其中将一个常数(通常为 |
|
一个平滑模型,它根据用户提供的权重(lambdas)取 unigrams、bigrams 和 trigrams 的加权平均值。线性插值没有任何默认值。必须提供所有参数( |
resp = client.search( index="test", suggest={ "text": "obel prize", "simple_phrase": { "phrase": { "field": "title.trigram", "size": 1, "smoothing": { "laplace": { "alpha": 0.7 } } } } }, ) print(resp)
const response = await client.search({ index: "test", suggest: { text: "obel prize", simple_phrase: { phrase: { field: "title.trigram", size: 1, smoothing: { laplace: { alpha: 0.7, }, }, }, }, }, }); console.log(response);
POST test/_search { "suggest": { "text" : "obel prize", "simple_phrase" : { "phrase" : { "field" : "title.trigram", "size" : 1, "smoothing" : { "laplace" : { "alpha" : 0.7 } } } } } }
候选生成器
编辑phrase
建议器使用候选生成器为给定文本中的每个术语生成可能的术语列表。单个候选生成器类似于为文本中的每个单独的术语调用的 term
建议器。生成器的输出随后与来自其他术语的候选组合在一起,以进行建议候选评分。
目前仅支持一种候选生成器类型,即 direct_generator
。Phrase suggest API 接受键 direct_generator
下的生成器列表;列表中的每个生成器都针对原始文本中的每个术语调用。
直接生成器
编辑直接生成器支持以下参数
|
从中获取候选建议的字段。这是一个必需选项,需要全局或按建议设置。 |
|
每个建议文本标记返回的最大更正数。 |
|
suggest 模式控制在每个分片上生成的建议中包含哪些建议。除了
|
|
候选建议被视为建议的最大编辑距离。只能是 1 到 2 之间的值。任何其他值都会导致抛出错误请求错误。默认为 2。 |
|
为了成为候选建议而必须匹配的最小前缀字符数。默认为 1。增加此数字可提高拼写检查性能。通常,拼写错误不会出现在术语的开头。 |
|
为了包含在内,建议文本术语必须具有的最小长度。默认为 4。 |
|
用于与 |
|
建议应出现在其中的文档数量的最小阈值。这可以指定为文档绝对数量或相对百分比。这可以通过仅建议高频词项来提高质量。默认为 0f,并且未启用。如果指定的值大于 1,则该数字不能是小数。此选项使用分片级文档频率。 |
|
为了包含在内,建议文本标记可以存在的最大文档数量阈值。可以是相对百分比数字(例如,0.4)或表示文档频率的绝对数字。如果指定的值大于 1,则不能指定小数。默认为 0.01f。这可用于排除高频词项(通常拼写正确),以免被拼写检查。这也提高了拼写检查性能。此选项使用分片级文档频率。 |
|
应用于传递给此候选生成器的每个标记的过滤器(分析器)。在生成候选之前,此过滤器将应用于原始标记。 |
|
应用于每个生成的标记(在它们传递给实际短语评分器之前)的过滤器(分析器)。 |
以下示例显示了带有两个生成器的 phrase
建议调用:第一个使用包含普通索引术语的字段,第二个使用使用 reverse
过滤器(标记以相反的顺序索引)索引术语的字段。这用于克服直接生成器需要恒定前缀以提供高性能建议的限制。pre_filter
和 post_filter
选项接受普通的分析器名称。
resp = client.search( index="test", suggest={ "text": "obel prize", "simple_phrase": { "phrase": { "field": "title.trigram", "size": 1, "direct_generator": [ { "field": "title.trigram", "suggest_mode": "always" }, { "field": "title.reverse", "suggest_mode": "always", "pre_filter": "reverse", "post_filter": "reverse" } ] } } }, ) print(resp)
const response = await client.search({ index: "test", suggest: { text: "obel prize", simple_phrase: { phrase: { field: "title.trigram", size: 1, direct_generator: [ { field: "title.trigram", suggest_mode: "always", }, { field: "title.reverse", suggest_mode: "always", pre_filter: "reverse", post_filter: "reverse", }, ], }, }, }, }); console.log(response);
POST test/_search { "suggest": { "text" : "obel prize", "simple_phrase" : { "phrase" : { "field" : "title.trigram", "size" : 1, "direct_generator" : [ { "field" : "title.trigram", "suggest_mode" : "always" }, { "field" : "title.reverse", "suggest_mode" : "always", "pre_filter" : "reverse", "post_filter" : "reverse" } ] } } } }
pre_filter
和 post_filter
还可用于在生成候选后注入同义词。例如,对于查询 captain usq
,我们可能会为术语 usq
生成候选 usa
,这是 america
的同义词。如果此短语得分足够高,这使我们能够向用户展示 captain america
。
Completion 建议器
编辑completion
建议器提供自动完成/边输入边搜索功能。这是一种导航功能,可以在用户输入时引导用户找到相关结果,从而提高搜索精度。它不适用于拼写校正或“您是不是要找”功能,例如 term
或 phrase
建议器。
理想情况下,自动完成功能应该与用户键入的速度一样快,以便提供与用户已键入内容相关的即时反馈。因此,completion
建议器针对速度进行了优化。该建议器使用可以快速查找的数据结构,但是构建成本很高并且存储在内存中。
映射
编辑要使用 completion
建议器,请将您要从中生成建议的字段映射为 completion
类型。这将索引该字段值以进行快速完成。
resp = client.indices.create( index="music", mappings={ "properties": { "suggest": { "type": "completion" } } }, ) print(resp)
response = client.indices.create( index: 'music', body: { mappings: { properties: { suggest: { type: 'completion' } } } } ) puts response
const response = await client.indices.create({ index: "music", mappings: { properties: { suggest: { type: "completion", }, }, }, }); console.log(response);
PUT music { "mappings": { "properties": { "suggest": { "type": "completion" } } } }
completion
字段的参数
编辑completion
字段接受以下参数
要使用的索引分析器,默认为 |
|
要使用的搜索分析器,默认为 |
|
|
保留分隔符,默认为 |
|
启用位置增量,默认为 |
|
限制单个输入的长度,默认为 |
索引
编辑您可以像索引任何其他字段一样索引建议。一个建议由一个 input
和一个可选的 weight
属性组成。input
是建议查询期望匹配的文本,而 weight
决定建议的评分方式。索引建议如下
resp = client.index( index="music", id="1", refresh=True, document={ "suggest": { "input": [ "Nevermind", "Nirvana" ], "weight": 34 } }, ) print(resp)
response = client.index( index: 'music', id: 1, refresh: true, body: { suggest: { input: [ 'Nevermind', 'Nirvana' ], weight: 34 } } ) puts response
const response = await client.index({ index: "music", id: 1, refresh: "true", document: { suggest: { input: ["Nevermind", "Nirvana"], weight: 34, }, }, }); console.log(response);
PUT music/_doc/1?refresh { "suggest" : { "input": [ "Nevermind", "Nirvana" ], "weight" : 34 } }
支持以下参数
|
要存储的输入,可以是字符串数组,也可以只是一个字符串。此字段为必填项。 此值不能包含以下 UTF-16 控制字符
|
|
一个正整数或一个包含正整数的字符串,定义权重并允许您对建议进行排名。此字段为可选字段。 |
您可以为文档索引多个建议,如下所示
resp = client.index( index="music", id="1", refresh=True, document={ "suggest": [ { "input": "Nevermind", "weight": 10 }, { "input": "Nirvana", "weight": 3 } ] }, ) print(resp)
response = client.index( index: 'music', id: 1, refresh: true, body: { suggest: [ { input: 'Nevermind', weight: 10 }, { input: 'Nirvana', weight: 3 } ] } ) puts response
const response = await client.index({ index: "music", id: 1, refresh: "true", document: { suggest: [ { input: "Nevermind", weight: 10, }, { input: "Nirvana", weight: 3, }, ], }, }); console.log(response);
PUT music/_doc/1?refresh { "suggest": [ { "input": "Nevermind", "weight": 10 }, { "input": "Nirvana", "weight": 3 } ] }
您可以使用以下简写形式。请注意,您不能使用简写形式指定建议的权重。
resp = client.index( index="music", id="1", refresh=True, document={ "suggest": [ "Nevermind", "Nirvana" ] }, ) print(resp)
response = client.index( index: 'music', id: 1, refresh: true, body: { suggest: [ 'Nevermind', 'Nirvana' ] } ) puts response
const response = await client.index({ index: "music", id: 1, refresh: "true", document: { suggest: ["Nevermind", "Nirvana"], }, }); console.log(response);
PUT music/_doc/1?refresh { "suggest" : [ "Nevermind", "Nirvana" ] }
查询
编辑建议的工作方式与往常相同,除了您必须将建议类型指定为 completion
。建议是近实时的,这意味着可以通过 refresh 使新的建议可见,并且一旦删除的文档将永远不会显示。此请求
resp = client.search( index="music", pretty=True, suggest={ "song-suggest": { "prefix": "nir", "completion": { "field": "suggest" } } }, ) print(resp)
response = client.search( index: 'music', pretty: true, body: { suggest: { "song-suggest": { prefix: 'nir', completion: { field: 'suggest' } } } } ) puts response
const response = await client.search({ index: "music", pretty: "true", suggest: { "song-suggest": { prefix: "nir", completion: { field: "suggest", }, }, }, }); console.log(response);
POST music/_search?pretty { "suggest": { "song-suggest": { "prefix": "nir", "completion": { "field": "suggest" } } } }
返回此响应
{ "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits": ... "took": 2, "timed_out": false, "suggest": { "song-suggest" : [ { "text" : "nir", "offset" : 0, "length" : 3, "options" : [ { "text" : "Nirvana", "_index": "music", "_id": "1", "_score": 1.0, "_source": { "suggest": ["Nevermind", "Nirvana"] } } ] } ] } }
必须启用 _source
元数据字段,这是默认行为,以启用使用建议返回 _source
。
配置的建议权重以 _score
的形式返回。text
字段使用已索引建议的 input
。 默认情况下,建议会返回完整的文档 _source
。 _source
的大小会因磁盘读取和网络传输开销而影响性能。 为了节省一些网络开销,请使用源过滤,从 _source
中过滤掉不必要的字段,以最小化 _source
的大小。 请注意,_suggest 端点不支持源过滤,但在 _search
端点上使用 suggest 是支持的。
resp = client.search( index="music", source="suggest", suggest={ "song-suggest": { "prefix": "nir", "completion": { "field": "suggest", "size": 5 } } }, ) print(resp)
response = client.search( index: 'music', body: { _source: 'suggest', suggest: { "song-suggest": { prefix: 'nir', completion: { field: 'suggest', size: 5 } } } } ) puts response
const response = await client.search({ index: "music", _source: "suggest", suggest: { "song-suggest": { prefix: "nir", completion: { field: "suggest", size: 5, }, }, }, }); console.log(response);
POST music/_search { "_source": "suggest", "suggest": { "song-suggest": { "prefix": "nir", "completion": { "field": "suggest", "size": 5 } } } }
应该类似于
{ "took": 6, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 0, "relation": "eq" }, "max_score": null, "hits": [] }, "suggest": { "song-suggest": [ { "text": "nir", "offset": 0, "length": 3, "options": [ { "text": "Nirvana", "_index": "music", "_id": "1", "_score": 1.0, "_source": { "suggest": [ "Nevermind", "Nirvana" ] } } ] } ] } }
基本的完成建议器查询支持以下参数
|
要在其上运行查询的字段名称(必需)。 |
|
要返回的建议数量(默认为 |
|
是否应过滤掉重复的建议(默认为 |
完成建议器会考虑索引中的所有文档。有关如何查询文档子集的说明,请参阅上下文建议器。
如果完成查询跨越多个分片,建议将分两个阶段执行,最后一个阶段从分片中获取相关文档,这意味着针对单个分片执行完成请求的性能更高,因为当建议跨越多个分片时,会产生文档获取开销。为了获得最佳的完成性能,建议将完成项索引到单个分片索引中。如果由于分片大小而导致堆使用率过高,仍然建议将索引分成多个分片,而不是优化完成性能。
跳过重复建议
编辑查询可能会返回来自不同文档的重复建议。可以通过将 skip_duplicates
设置为 true 来修改此行为。设置后,此选项会从结果中过滤掉具有重复建议的文档。
resp = client.search( index="music", pretty=True, suggest={ "song-suggest": { "prefix": "nor", "completion": { "field": "suggest", "skip_duplicates": True } } }, ) print(resp)
response = client.search( index: 'music', pretty: true, body: { suggest: { "song-suggest": { prefix: 'nor', completion: { field: 'suggest', skip_duplicates: true } } } } ) puts response
const response = await client.search({ index: "music", pretty: "true", suggest: { "song-suggest": { prefix: "nor", completion: { field: "suggest", skip_duplicates: true, }, }, }, }); console.log(response);
POST music/_search?pretty { "suggest": { "song-suggest": { "prefix": "nor", "completion": { "field": "suggest", "skip_duplicates": true } } } }
当设置为 true 时,此选项可能会降低搜索速度,因为需要访问更多建议才能找到前 N 个。
模糊查询
编辑完成建议器还支持模糊查询 — 这意味着您的搜索中可能存在拼写错误,但仍然可以获得结果。
resp = client.search( index="music", pretty=True, suggest={ "song-suggest": { "prefix": "nor", "completion": { "field": "suggest", "fuzzy": { "fuzziness": 2 } } } }, ) print(resp)
response = client.search( index: 'music', pretty: true, body: { suggest: { "song-suggest": { prefix: 'nor', completion: { field: 'suggest', fuzzy: { fuzziness: 2 } } } } } ) puts response
const response = await client.search({ index: "music", pretty: "true", suggest: { "song-suggest": { prefix: "nor", completion: { field: "suggest", fuzzy: { fuzziness: 2, }, }, }, }, }); console.log(response);
POST music/_search?pretty { "suggest": { "song-suggest": { "prefix": "nor", "completion": { "field": "suggest", "fuzzy": { "fuzziness": 2 } } } } }
与查询 prefix
共享最长前缀的建议将获得更高的评分。
模糊查询可以接受特定的模糊参数。支持以下参数
|
模糊因子,默认为 |
|
如果设置为 |
|
返回模糊建议之前输入的最小长度,默认为 |
|
不检查模糊替代方案的输入的最小长度,默认为 |
|
如果 |
如果您想坚持使用默认值,但仍然使用模糊查询,您可以使用 fuzzy: {}
或 fuzzy: true
。
正则表达式查询
编辑完成建议器还支持正则表达式查询,这意味着您可以将前缀表示为正则表达式
resp = client.search( index="music", pretty=True, suggest={ "song-suggest": { "regex": "n[ever|i]r", "completion": { "field": "suggest" } } }, ) print(resp)
response = client.search( index: 'music', pretty: true, body: { suggest: { "song-suggest": { regex: 'n[ever|i]r', completion: { field: 'suggest' } } } } ) puts response
const response = await client.search({ index: "music", pretty: "true", suggest: { "song-suggest": { regex: "n[ever|i]r", completion: { field: "suggest", }, }, }, }); console.log(response);
POST music/_search?pretty { "suggest": { "song-suggest": { "regex": "n[ever|i]r", "completion": { "field": "suggest" } } } }
正则表达式查询可以接受特定的正则表达式参数。支持以下参数
|
可能的标志包括 |
|
正则表达式很危险,因为很容易意外地创建一个看似无害的正则表达式,该正则表达式需要 Lucene 执行指数级的内部确定性自动机状态(以及相应的 RAM 和 CPU)。Lucene 使用 |
上下文建议器
编辑完成建议器会考虑索引中的所有文档,但通常需要提供按某些条件过滤和/或提升的建议。例如,您希望按某些艺术家过滤歌曲标题,或者您希望根据歌曲的类型来提升歌曲标题。
为了实现建议过滤和/或提升,您可以在配置完成字段时添加上下文映射。您可以为一个完成字段定义多个上下文映射。每个上下文映射都有一个唯一的名称和一个类型。有两种类型:category
和 geo
。上下文映射在字段映射中的 contexts
参数下配置。
在索引和查询启用上下文的完成字段时,必须提供上下文。
允许的最大完成字段上下文映射数为 10。
以下定义了类型,每种类型都为完成字段提供了两个上下文映射
resp = client.indices.create( index="place", mappings={ "properties": { "suggest": { "type": "completion", "contexts": [ { "name": "place_type", "type": "category" }, { "name": "location", "type": "geo", "precision": 4 } ] } } }, ) print(resp) resp1 = client.indices.create( index="place_path_category", mappings={ "properties": { "suggest": { "type": "completion", "contexts": [ { "name": "place_type", "type": "category", "path": "cat" }, { "name": "location", "type": "geo", "precision": 4, "path": "loc" } ] }, "loc": { "type": "geo_point" } } }, ) print(resp1)
response = client.indices.create( index: 'place', body: { mappings: { properties: { suggest: { type: 'completion', contexts: [ { name: 'place_type', type: 'category' }, { name: 'location', type: 'geo', precision: 4 } ] } } } } ) puts response response = client.indices.create( index: 'place_path_category', body: { mappings: { properties: { suggest: { type: 'completion', contexts: [ { name: 'place_type', type: 'category', path: 'cat' }, { name: 'location', type: 'geo', precision: 4, path: 'loc' } ] }, loc: { type: 'geo_point' } } } } ) puts response
const response = await client.indices.create({ index: "place", mappings: { properties: { suggest: { type: "completion", contexts: [ { name: "place_type", type: "category", }, { name: "location", type: "geo", precision: 4, }, ], }, }, }, }); console.log(response); const response1 = await client.indices.create({ index: "place_path_category", mappings: { properties: { suggest: { type: "completion", contexts: [ { name: "place_type", type: "category", path: "cat", }, { name: "location", type: "geo", precision: 4, path: "loc", }, ], }, loc: { type: "geo_point", }, }, }, }); console.log(response1);
PUT place { "mappings": { "properties": { "suggest": { "type": "completion", "contexts": [ { "name": "place_type", "type": "category" }, { "name": "location", "type": "geo", "precision": 4 } ] } } } } PUT place_path_category { "mappings": { "properties": { "suggest": { "type": "completion", "contexts": [ { "name": "place_type", "type": "category", "path": "cat" }, { "name": "location", "type": "geo", "precision": 4, "path": "loc" } ] }, "loc": { "type": "geo_point" } } } }
定义一个名为 place_type 的 |
|
定义一个名为 location 的 |
|
定义一个名为 place_type 的 |
|
定义一个名为 location 的 |
添加上下文映射会增加完成字段的索引大小。完成索引完全驻留在堆中,您可以使用索引统计信息来监视完成字段索引大小。
类别上下文
编辑category
上下文允许您在索引时将一个或多个类别与建议相关联。在查询时,可以通过其关联的类别来过滤和提升建议。
映射的设置方式类似于上面的 place_type
字段。如果定义了 path
,则类别将从文档中的该路径读取,否则它们必须像这样在 suggest 字段中发送
resp = client.index( index="place", id="1", document={ "suggest": { "input": [ "timmy's", "starbucks", "dunkin donuts" ], "contexts": { "place_type": [ "cafe", "food" ] } } }, ) print(resp)
response = client.index( index: 'place', id: 1, body: { suggest: { input: [ "timmy's", 'starbucks', 'dunkin donuts' ], contexts: { place_type: [ 'cafe', 'food' ] } } } ) puts response
const response = await client.index({ index: "place", id: 1, document: { suggest: { input: ["timmy's", "starbucks", "dunkin donuts"], contexts: { place_type: ["cafe", "food"], }, }, }, }); console.log(response);
PUT place/_doc/1 { "suggest": { "input": [ "timmy's", "starbucks", "dunkin donuts" ], "contexts": { "place_type": [ "cafe", "food" ] } } }
如果映射具有 path
,则以下索引请求足以添加类别
resp = client.index( index="place_path_category", id="1", document={ "suggest": [ "timmy's", "starbucks", "dunkin donuts" ], "cat": [ "cafe", "food" ] }, ) print(resp)
response = client.index( index: 'place_path_category', id: 1, body: { suggest: [ "timmy's", 'starbucks', 'dunkin donuts' ], cat: [ 'cafe', 'food' ] } ) puts response
const response = await client.index({ index: "place_path_category", id: 1, document: { suggest: ["timmy's", "starbucks", "dunkin donuts"], cat: ["cafe", "food"], }, }); console.log(response);
PUT place_path_category/_doc/1 { "suggest": ["timmy's", "starbucks", "dunkin donuts"], "cat": ["cafe", "food"] }
如果上下文映射引用另一个字段并且类别已显式索引,则建议将使用两组类别进行索引。
类别查询
编辑可以按一个或多个类别过滤建议。以下按多个类别过滤建议
resp = client.search( index="place", pretty=True, suggest={ "place_suggestion": { "prefix": "tim", "completion": { "field": "suggest", "size": 10, "contexts": { "place_type": [ "cafe", "restaurants" ] } } } }, ) print(resp)
response = client.search( index: 'place', pretty: true, body: { suggest: { place_suggestion: { prefix: 'tim', completion: { field: 'suggest', size: 10, contexts: { place_type: [ 'cafe', 'restaurants' ] } } } } } ) puts response
const response = await client.search({ index: "place", pretty: "true", suggest: { place_suggestion: { prefix: "tim", completion: { field: "suggest", size: 10, contexts: { place_type: ["cafe", "restaurants"], }, }, }, }, }); console.log(response);
POST place/_search?pretty { "suggest": { "place_suggestion": { "prefix": "tim", "completion": { "field": "suggest", "size": 10, "contexts": { "place_type": [ "cafe", "restaurants" ] } } } } }
如果在查询中设置了多个类别或类别上下文,它们将合并为析取。这意味着如果建议包含至少一个提供的上下文值,则会匹配。
具有某些类别的建议可以比其他建议得到更高的提升。以下按类别过滤建议,并另外提升与某些类别关联的建议
resp = client.search( index="place", pretty=True, suggest={ "place_suggestion": { "prefix": "tim", "completion": { "field": "suggest", "size": 10, "contexts": { "place_type": [ { "context": "cafe" }, { "context": "restaurants", "boost": 2 } ] } } } }, ) print(resp)
response = client.search( index: 'place', pretty: true, body: { suggest: { place_suggestion: { prefix: 'tim', completion: { field: 'suggest', size: 10, contexts: { place_type: [ { context: 'cafe' }, { context: 'restaurants', boost: 2 } ] } } } } } ) puts response
const response = await client.search({ index: "place", pretty: "true", suggest: { place_suggestion: { prefix: "tim", completion: { field: "suggest", size: 10, contexts: { place_type: [ { context: "cafe", }, { context: "restaurants", boost: 2, }, ], }, }, }, }, }); console.log(response);
POST place/_search?pretty { "suggest": { "place_suggestion": { "prefix": "tim", "completion": { "field": "suggest", "size": 10, "contexts": { "place_type": [ { "context": "cafe" }, { "context": "restaurants", "boost": 2 } ] } } } } }
除了接受类别值之外,上下文查询还可以由多个类别上下文子句组成。对于 category
上下文子句,支持以下参数
|
要过滤/提升的类别的的值。这是必需的。 |
|
建议的分数应提升的因子,分数是通过将提升因子与建议权重相乘来计算的,默认为 |
|
是否应将类别值视为前缀。例如,如果设置为 |
如果建议条目匹配多个上下文,则最终得分将计算为任何匹配上下文产生的最大得分。
地理位置上下文
编辑geo
上下文允许您在索引时将一个或多个地理点或地理散列与建议相关联。在查询时,如果建议在指定地理位置的某个距离内,则可以过滤和提升建议。
在内部,地理点会编码为具有指定精度的地理散列。
地理映射
编辑除了 path
设置之外,geo
上下文映射还接受以下设置
|
这定义了要索引的地理散列的精度,可以指定为距离值( |
索引时 precision
设置设置了查询时可以使用的最大地理散列精度。
索引地理上下文
编辑geo
上下文可以显式设置为建议,也可以通过 path
参数从文档中的地理点字段索引,类似于 category
上下文。将多个地理位置上下文与建议关联,将为每个地理位置索引该建议。以下索引包含两个地理位置上下文的建议
resp = client.index( index="place", id="1", document={ "suggest": { "input": "timmy's", "contexts": { "location": [ { "lat": 43.6624803, "lon": -79.3863353 }, { "lat": 43.6624718, "lon": -79.3873227 } ] } } }, ) print(resp)
response = client.index( index: 'place', id: 1, body: { suggest: { input: "timmy's", contexts: { location: [ { lat: 43.6624803, lon: -79.3863353 }, { lat: 43.6624718, lon: -79.3873227 } ] } } } ) puts response
const response = await client.index({ index: "place", id: 1, document: { suggest: { input: "timmy's", contexts: { location: [ { lat: 43.6624803, lon: -79.3863353, }, { lat: 43.6624718, lon: -79.3873227, }, ], }, }, }, }); console.log(response);
PUT place/_doc/1 { "suggest": { "input": "timmy's", "contexts": { "location": [ { "lat": 43.6624803, "lon": -79.3863353 }, { "lat": 43.6624718, "lon": -79.3873227 } ] } } }
地理位置查询
编辑可以根据建议与一个或多个地理点的接近程度来过滤和提升建议。以下过滤落在地理点的编码地理散列所代表区域内的建议
resp = client.search( index="place", suggest={ "place_suggestion": { "prefix": "tim", "completion": { "field": "suggest", "size": 10, "contexts": { "location": { "lat": 43.662, "lon": -79.38 } } } } }, ) print(resp)
response = client.search( index: 'place', body: { suggest: { place_suggestion: { prefix: 'tim', completion: { field: 'suggest', size: 10, contexts: { location: { lat: 43.662, lon: -79.38 } } } } } } ) puts response
const response = await client.search({ index: "place", suggest: { place_suggestion: { prefix: "tim", completion: { field: "suggest", size: 10, contexts: { location: { lat: 43.662, lon: -79.38, }, }, }, }, }, }); console.log(response);
POST place/_search { "suggest": { "place_suggestion": { "prefix": "tim", "completion": { "field": "suggest", "size": 10, "contexts": { "location": { "lat": 43.662, "lon": -79.380 } } } } } }
当在查询时指定较低精度的位置时,将考虑该区域内的所有建议。
如果在查询中设置了多个类别或类别上下文,它们将合并为析取。这意味着如果建议包含至少一个提供的上下文值,则会匹配。
位于由地理散列表示的区域内的建议也可以比其他建议得到更高的提升,如下所示
resp = client.search( index="place", pretty=True, suggest={ "place_suggestion": { "prefix": "tim", "completion": { "field": "suggest", "size": 10, "contexts": { "location": [ { "lat": 43.6624803, "lon": -79.3863353, "precision": 2 }, { "context": { "lat": 43.6624803, "lon": -79.3863353 }, "boost": 2 } ] } } } }, ) print(resp)
response = client.search( index: 'place', pretty: true, body: { suggest: { place_suggestion: { prefix: 'tim', completion: { field: 'suggest', size: 10, contexts: { location: [ { lat: 43.6624803, lon: -79.3863353, precision: 2 }, { context: { lat: 43.6624803, lon: -79.3863353 }, boost: 2 } ] } } } } } ) puts response
const response = await client.search({ index: "place", pretty: "true", suggest: { place_suggestion: { prefix: "tim", completion: { field: "suggest", size: 10, contexts: { location: [ { lat: 43.6624803, lon: -79.3863353, precision: 2, }, { context: { lat: 43.6624803, lon: -79.3863353, }, boost: 2, }, ], }, }, }, }, }); console.log(response);
POST place/_search?pretty { "suggest": { "place_suggestion": { "prefix": "tim", "completion": { "field": "suggest", "size": 10, "contexts": { "location": [ { "lat": 43.6624803, "lon": -79.3863353, "precision": 2 }, { "context": { "lat": 43.6624803, "lon": -79.3863353 }, "boost": 2 } ] } } } } }
上下文查询会筛选精度为 2 的 (43.662, -79.380) 的地理散列所表示的地理位置下的建议,并提升默认精度为 6 的 (43.6624803, -79.3863353) 的地理散列表示的建议,提升因子为 |
如果建议条目匹配多个上下文,则最终得分将计算为任何匹配上下文产生的最大得分。
除了接受上下文值之外,上下文查询还可以由多个上下文子句组成。对于 geo
上下文子句,支持以下参数
|
用于过滤或提升建议的地理点对象或地理散列字符串。这是必需的。 |
|
建议的分数应提升的因子,分数是通过将提升因子与建议权重相乘来计算的,默认为 |
|
用于编码查询地理位置点的地理哈希精度。可以将其指定为距离值(例如, |
|
接受一个精度值数组,用于指定应考虑哪些相邻的地理哈希。精度值可以是距离值(例如, |
精度字段不会导致距离匹配。指定类似 10km
的距离值只会产生一个表示该大小的瓦片的地理哈希精度值。该精度将用于将搜索地理位置点编码为地理哈希瓦片以进行完成匹配。这样做的一个后果是,即使非常靠近搜索点的瓦片之外的点也不会被匹配。降低精度或增加距离可以降低这种情况发生的风险,但不能完全消除它。
返回建议器的类型
编辑有时你需要知道建议器的确切类型才能解析其结果。typed_keys
参数可以用来更改响应中建议器的名称,使其以其类型为前缀。
考虑以下示例,其中有两个建议器 term
和 phrase
resp = client.search( typed_keys=True, suggest={ "text": "some test mssage", "my-first-suggester": { "term": { "field": "message" } }, "my-second-suggester": { "phrase": { "field": "message" } } }, ) print(resp)
response = client.search( typed_keys: true, body: { suggest: { text: 'some test mssage', "my-first-suggester": { term: { field: 'message' } }, "my-second-suggester": { phrase: { field: 'message' } } } } ) puts response
const response = await client.search({ typed_keys: "true", suggest: { text: "some test mssage", "my-first-suggester": { term: { field: "message", }, }, "my-second-suggester": { phrase: { field: "message", }, }, }, }); console.log(response);
POST _search?typed_keys { "suggest": { "text" : "some test mssage", "my-first-suggester" : { "term" : { "field" : "message" } }, "my-second-suggester" : { "phrase" : { "field" : "message" } } } }
在响应中,建议器的名称将分别更改为 term#my-first-suggester
和 phrase#my-second-suggester
,反映每个建议的类型
{ "suggest": { "term#my-first-suggester": [ { "text": "some", "offset": 0, "length": 4, "options": [] }, { "text": "test", "offset": 5, "length": 4, "options": [] }, { "text": "mssage", "offset": 10, "length": 6, "options": [ { "text": "message", "score": 0.8333333, "freq": 4 } ] } ], "phrase#my-second-suggester": [ { "text": "some test mssage", "offset": 0, "length": 16, "options": [ { "text": "some test message", "score": 0.030227963 } ] } ] }, ... }