在这篇文章中,我们来讲述Elasticsearch中的suggester。通过使用suggester,根据提供的文本建议外观相似的字词。 建议功能的某些部分仍在开发中。suggester的官方文档在地址https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters.html
Term suggestion 功能适用于一下文本编辑软件。在知道该词语是错误的情况下提供一些正确词的候选者。
比如上面的谷歌编辑器或者微软的WORD文本编辑器中就会用一个红色的波浪线显示documnt是错误的。当我们把鼠标放到改词上面时,它会自动显示一个正确的document作为候选的正确的词。
用户经常在搜索查询中犯拼写错误。 即使查询中存在拼写错误,可行的搜索解决方案也必须能够提供建议。 建议API提供了两种此类拼写检查API,即术语建议和短语建议。 术语建议API旨在纠正错误键入的单词的拼写。 反过来,短语建议API是处理多个术语的,是建议API一词的高级版本。 让我们更详细地讨论术语“建议API”及其功能。
测试文档:
我们在Kibana中打入如下的bulk API命令:
POST _bulk
{ "index" : { "_index" : "term-suggest", "_id": 1 }}
{ "name": "bald"}
{ "index" : { "_index" : "term-suggest", "_id": 2 }}
{ "name": "bold"}
{ "index" : { "_index" : "term-suggest", "_id": 3 }}
{ "name": "blend"}
{ "index" : { "_index" : "term-suggest", "_id": 4 }}
{ "name": "blood"}
这样在我们的 term-suggest 索引中就有四个文档。每个文档含有一个叫做name的字段。
用例1 - term suggester
现在索引已包含必要的文档,让我们通过建议查询来演示如何查询拼写错误的单词以及如何显示更正。 将以下建议查询传递给索引:
GET term-suggest/_search
{
"query": {
"match": {
"name": "bold"
}
},
"suggest": {
"my-suggestion": {
"text": "bleed",
"term": {
"field": "name"
}
}
}
}
请求:
建议功能通过使用建议,根据提供的文本提示外观相似的术语。 建议请求部分在_search请求中与查询部分一起定义。 如果查询部分被忽略,则仅返回建议。在上面我们同时使用了query及suggest。显示结果:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.2039728,
"hits" : [
{
"_index" : "term-suggest",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.2039728,
"_source" : {
"name" : "bold"
}
}
]
},
"suggest" : {
"my-suggestion" : [
{
"text" : "bleed",
"offset" : 0,
"length" : 5,
"options" : [
{
"text" : "blend",
"score" : 0.8,
"freq" : 1
},
{
"text" : "blood",
"score" : 0.6,
"freq" : 1
}
]
}
]
}
}
上面的结果显示:我们找到一个name字段为bold的文档,同时我么也找到了bleed这个术语的被建议的术语:blend及blood。请注意bleed并不存在于我们的索引之中。从上面的结果中,我们也可以看到在options中返回的结果中有score。这个分数越高,表明匹配度越高。
假如我们用正确的已经存在于索引之中的词来使用term suggest:
GET term-suggest/_search
{
"suggest": {
"my-suggestion": {
"text": "blood",
"term": {
"field": "name"
}
}
}
}
那么显示的结果是:
"suggest" : {
"my-suggestion" : [
{
"text" : "blood",
"offset" : 0,
"length" : 5,
"options" : [ ]
}
]
}
我们可以看出来没有任何的建议的术语。
用例2 - Multi-term suggester
另一个有用的功能是multi-term建议请求。 在这里,我们可以在同一个建议查询中打包几个术语建议请求。 在下面的示例中查看其工作方式:
GET term-suggest/_search
{
"suggest": {
"my-suggest": {
"text": "bleed",
"term": {
"field": "name"
}
},
"my-suggest2": {
"text": "blod",
"term": {
"field": "name"
}
}
}
}
在上面的示例中,我们仅对一个字段(“name”)使用了拼写检查。 我们也可以通过简单地用另一个替换“ field”值来对多个字段做同样的事情。显示结果:
"suggest" : {
"my-suggest" : [
{
"text" : "bleed",
"offset" : 0,
"length" : 5,
"options" : [
{
"text" : "blend",
"score" : 0.8,
"freq" : 1
},
{
"text" : "blood",
"score" : 0.6,
"freq" : 1
}
]
}
],
"my-suggest2" : [
{
"text" : "blod",
"offset" : 0,
"length" : 4,
"options" : [
{
"text" : "blood",
"score" : 0.75,
"freq" : 1
},
{
"text" : "bold",
"score" : 0.75,
"freq" : 1
},
{
"text" : "bald",
"score" : 0.5,
"freq" : 1
},
{
"text" : "blend",
"score" : 0.5,
"freq" : 1
}
]
}
]
}
在返回的结果中我们可以看到有两个不同的数组my-suggest及my-suggest2。
用例3 - 全局建议文字
为了避免重复建议文本,我们可以定义一个全局文本。 在下面的示例中,建议文本是全局定义的,它适用于我们指定的两个建议查询。 当您针对索引中的两个不同字段发送建议查询时,此功能很有用。 假设索引中还有另一个字段“substance”,我们可以使用全局文本创建以下建议查询。
GET term-suggest/_search
{
"suggest": {
"text": "blod",
"my-suggest": {
"term": {
"field": "name"
}
},
"my-suggest2": {
"term": {
"field": "substance"
}
}
}
}
在以上请求中,我们可以看到为建议查询定义了全局建议文本“blod”,并且两个子查询针对索引中的两个字段使用此文本。 这样,我们可以一次定义一个全局文本,然后将其自动重用于许多字段。