elasticsearch之建议器简介


首先,环境是elasticsearch版本是5.x以上。低版本的没有测试!

目前为止,浏览器都已经具备Suggest as you type功能,即在我们输入搜索的过程中,进行自动的补全或者纠错功能,协助用户输入更精确的关键词,提高搜索阶段的文档匹配程度。例如我们在百度或谷歌浏览器输入搜索关键词时,虽然我们输入的有误,但是浏览器依然能够提示出我们想要的正确结果。

在谷歌浏览器中,再输入刚开始时,会自动补全,而当输入内容达到一定长度时,如果因为单词拼写错误而无法补全时,就开始尝试提示相似的词。

这些功能,我们能通过elasticsearch实现吗?答案就在Suggesters API中。
在elasticsearch中,建议功能通过使用建议器基于提供的文本建议类似的词(官网说部分功能仍在开发中.........)。
注意,目前_suggest已经弃用,我们可以通过_search来做建议器的查询。在5.0版本中,_search经过优化,变得非常的方便。

PUT s1
{
  "mappings": {
    "doc": {
      "properties": {
        "title": {
          "type": "text",
          "analyzer": "standard"
        }
      }
    }
  }
}

PUT s1/doc/1
{
  "title": "Lucene is cool"
}

PUT s1/doc/2
{
  "title":"Elasticsearch builds on top of lucene"
}

GET s1/doc/_search
{
  "query": {
    "match": {
      "title": "Lucene"
    }
  },
  "suggest": {
    "my_suggest": {
      "text": "Elasticsear lucen",
      "term": {
        "field": "title"
      }
    }
  }
}

上例是一个包含建议的查询请求,查询query我们已经了然。
让我们注意suggest,每个建议器都有自己名称my-suggestion,es根据text字段返回建议结果。建议类型是term。从field字段生成建议。

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "s1",
        "_type" : "doc",
        "_id" : "2",
        "_score" : 0.2876821,
        "_source" : {
          "title" : "Elasticsearch builds on top of lucene"
        }
      },
      {
        "_index" : "s1",
        "_type" : "doc",
        "_id" : "1",
        "_score" : 0.2876821,
        "_source" : {
          "title" : "Lucene is cool"
        }
      }
    ]
  },
  "suggest" : {
    "my_suggest" : [
      {
        "text" : "elasticsear",
        "offset" : 0,
        "length" : 11,
        "options" : [
          {
            "text" : "elasticsearch",
            "score" : 0.8181818,
            "freq" : 1
          }
        ]
      },
      {
        "text" : "lucen",
        "offset" : 12,
        "length" : 5,
        "options" : [
          {
            "text" : "lucene",
            "score" : 0.8,
            "freq" : 2
          }
        ]
      }
    ]
  }
}

正如结果所示。对于输入的每个词条的建议结果,es都会放在options中,如果没有建议结果,options将会为空。
如果我们仅需要建议而不需要查询功能,我们可以忽略query而直接使用suggest对象返回建议:

GET s1/doc/_search
{
  "suggest": {
    "my_sugget": {
      "text": "Elasticsear lucen",
      "term": {
        "field": "title"
      }
    }
  }
}

可以根据需要指定几组建议器,每组建议器都有自己的名称。如下例的my_suggest1my_suggest2

GET s1/doc/_search
{
  "suggest": {
    "my_sugget1": {
      "text": "Elasticsear",
      "term": {
        "field": "title"
      }
    },
    "my_suggest2": {
      "text": "lucen",
      "term": {
        "field": "title"
      }
    }
  }
}

在多个建议器中,如果输入的text字段值一致,可以单独写出来,以适用于my_suggest1my_suggest2两个建议器:

GET s1/doc/_search
{
  "suggest": {
    "text": "Elasticsear lucen",
    "my_sugget1": {
      "term": {
        "field": "title"
      }
    },
    "my_suggest2": {
      "term": {
        "field": "title"
      }
    }
  }
}

根据需求不同elasticsearch设计了4种suggester,分别是:

  • 词条建议器(term suggester):对于给定文本的每个词条,该键议器从索引中抽取要建议的关键词,这对于短字段(如分类标签)很有效。
  • 词组建议器(phrase suggester):我们可以认为它是词条建议器的扩展,为整个文本(而不是单个词条)提供了替代方案,它考虑了各词条彼此临近出现的频率,使得该建议器更适合较长的字段,比如商品的描述。
  • 完成建议器(completion suggester):该建议器根据词条的前缀,提供自动完成的功能(智能提示,有点最左前缀查询的意思),为了实现这种实时的建议功能,它得到了优化,工作在内存中。所以,速度要比之前说的match_phrase_prefix快的多!
  • 上下文建议器(context suggester):它是完成建议器的扩展,允许我们根据词条或分类亦或是地理位置对结果进行过滤。