推荐,补全与高亮

我们在使用搜索引擎时,在输入框输入字符时,索引引擎往往会在下拉框给出推荐和提示。在ES中,该功能是通过“suggest”功能来提供的。通过将输入字符串拆分成词组项表,然后在ES的词典中进行搜索。

从总体来看,推荐可分为两大类四小类,即

Suggest:term suggest & phrase suggest

Completion:Completion suggest & Contexts suggest

推荐

推荐分为两种,即term suggest和pharse suggest。

Term Suggest

term suggest使用类似下面的模板。

GET xxx_index/_search
{
    "query": { *query block*},
    "suggester": {
        "suggest_name1": { // suggest的名称
            "text": "query_msg",  // 查询字符串
            "term": {
                "size": 10,    // 最大返回的suggest数目
                "field": "xxxx",  // 要推荐的字段名称
                "suggester_mode": "missing|popular|always" // 3种类型的suggester mode
            }
        },
        "suggest_name2": {
          "text": "nucene",
          "term": {
            "sort": "score",
            "field": "body",
            "string_distance": "levenshtein",
            "max_edits": 2,
            "prefix_length": 0,
            "suggest_mode": "missing"
          }
        }
    }
}

term suggest可以使用三种suggester mode

"missing",当搜索结果中已经包含要搜索的内容,则不进行推荐。

"popular",推荐全部文档中出现频率最高的内容。

"always",无论是否有结果,都进行推荐。

推荐的内容是通过计算编辑距离来进行的,在配置参数时,可以设置:

  1. string_distance,编辑距离的计算方法。
  2. sort,选择推荐结果的排序方法,可选的方式有两种,score和frequercy。
  3. max_edits,最大的编辑距离,只能设置1或者2,默认为2
  4. prefix_length,前缀匹配长度,默认为1,即推荐时至少第一个字符时匹配的,比如,要搜索lucene,如果我输入nucene,则不会有任何推荐结果返回。如果将prefix_length设成0,则能够正常推荐lucene。

Term Suggest的其他一些使用参考此处不做赘述,可参考:

https://www.elastic.co/guide/en/elasticsearch/reference/7.2/search-suggesters-term.html

Phrase Suggest

Phrase Suggest与Term Suggest的区别在于,term suggest会将输入拆成一个个词项分别进行搜索推荐,而phrase Suggest会将其作为一个整体进行。此处还有很多细节,官方文档中,使用了将一个字段加入了多个字段使用不同的处理方式进行解析的方式作为例子,有兴趣可以参考:

https://www.elastic.co/guide/en/elasticsearch/reference/7.2/search-suggesters-phrase.html

Term Suggest

GET articles/_search
{
  "suggest": {
    "YOUR_SUGGESTION": {
      "text": "elasticsearch is",
      "term": {
        "field": "body"
      }
    }
  }
}
 
 "suggest" : {
    "YOUR_SUGGESTION" : [
      {
        "text" : "elasticsearch",
        "offset" : 0,
        "length" : 13,
        "options" : [ ]
      },
      {
        "text" : "is",
        "offset" : 14,
        "length" : 2,
        "options" : [ ]
      }
    ]
  }

Phrase Suggest

GET articles/_search
{
  "suggest": {
    "YOUR_SUGGESTION": {
      "text": "elasticsearch is",
      "phrase": {
        "field": "body"
      }
    }
  }
}

...
  "suggest" : {
    "YOUR_SUGGESTION" : [
      {
        "text" : "elasticsearch is",
        "offset" : 0,
        "length" : 16,
        "options" : [ ]
      }
    ]
  }

几个常用参数:

"max_errors",表示输入中最多有几个拼写错误,一般推荐设置一个较低的值,如1,2

"confidence",置信度,设为1时,只有分数超过输入词组的项才会返回,当设为0时,top N结果都会返回。

补全

Completion Suggest

补全需要在做mapping时为相关的字段设置completion类型。

PUT articles
{
  "mappings": {
    "properties": {
      "title": {
        "type": "completion"
      }
    }
  }
}

mapping时,可以指定该字段的analyzer和search_analyzer。以及确定是否可以忽略分隔字符(使用参数preserve_separators)

同时也可以有一些其他设置。参考文档:

https://www.elastic.co/guide/en/elasticsearch/reference/7.2/search-suggesters-completion.html

在使用时,使用”completion“类型的suggest进行。

GET articles/_search?pretty
{
  "size": 20,
  "suggest": {
    "my_suggestion": {
      "prefix": "elk",
      "completion": {
        "field": "title"
      }
    }
  }
}

Context Suggest

另外,补全功能还可以根据上下文提示进行。比如,对输入“star”进行提示,如果我搜索的是“film”类型,则返回“star war”,如果是“coffee”类型,则返回“star bucks",这个功能是通过在文档写入时,增加类型标签来实现的。

PUT articles
{
  "mappings": {
    "properties": {
      "title": {
        "type": "completion",
        "contexts": [{
          "type": "category",
          "name": "item_type"
        }]
      }
    }
  }
}

插入数据

POST articles/_doc/2
{
  "title": {
    "input": ["Star War", "Lord of rings"],
    "contexts": {
      "item_type": ["film"]
    }
  }
}

POST articles/_doc/1
{
  "title": {
    "input": ["star bulk", "costa coffee"],
    "contexts": {
      "item_type": ["coffee"]
    }
  }
}

进行基于上下文的推荐

POST articles/_search
{
  "suggest": {
    "YOUR_SUGGESTION": {
      "prefix": "star",
      "completion": {
        "field": "title",
        "contexts": {
          "item_type": ["coffee"]
        }
      }
    }
  }
}

返回结果是:

....
            "text" : "star bulk",
            "_index" : "articles",
            "_type" : "_doc",
            "_id" : "1",
            "_score" : 1.0,
            "_source" : {
              "title" : {
                "input" : [
                  "star bulk",
                  "costa coffee"
                ],
                "contexts" : {
                  "item_type" : [
                    "coffee"
                  ]
                }
              }
            },
            "contexts" : {
              "item_type" : [
                "coffee"
              ]
            }
          }

基于上下文的补全推荐目前有两种类型,除了上文的category以外,还可以指定一个geo类型的context进行推荐。

高亮

高亮最简单的用法,就是在query块下面设置,需要高亮的fields,这样就会在搜索结果中将命中的部分用标签包括起来。

GET articles/_search
{
  "query": {
    "match": {
      "body": "elastic"
    }
  },
  "highlight": {
    "fields": {"body": {}},
    "pre_tags": "<aaa>",
    "post_tags": "</aaa>"
  }
}

高亮可以定制前缀标签和后缀标签。

另有一些更高级的应用可以参考官方文档。https://www.elastic.co/guide/en/elasticsearch/reference/7.2/search-request-highlighting.html

小结

从性能上看,由于补全功能都是基于前缀匹配提供的,而且使用了独立于倒排索引的FST数据结构,其性能最高,而Term Suggest会进行分词,因此性能不如phrase suggest,从性能上看是:

Completion > Phrase > Term

从精准度来看,

Completion > Phrase > Term

从查全角度(召回率)看,

Term > Phrase > Completion

如果想知道某次suggest的类型,可以在其search API上加入typed_keys参数

POST articles/_search?typed_keys
{
  "suggest": {
    "YOUR_SUGGESTION": {
      "prefix": "star",
      "completion": {
        "field": "title",
        "contexts": {
          "item_type": ["coffee"]
        }
      }
    }
  }
}

返回结果中会包含suggest的类型:

  "completion#YOUR_SUGGESTION" : [
      {
        "text" : "star",
        "offset" : 0,
        "length" : 4,
        "options" : [
          {
            "text" : "star bulk",
            "_index" : "articles",
            

今天是ES认证复习的第一轮结束,粗略的把ES的相关内容过了一遍,有很多地方都没有详细地进去看。比如本章的高亮部分,其实官方文档的内容很多,但是是否都需要细细地去学习呢?我觉得也许用处不大,没有实际的应用场景,也许我细细地看过,写了文章,又很快地忘记了。我觉得实践是非常重要的,亲自在kibana里面敲一遍,印象会比较深刻。有很多东西,文章看很多遍,不实际操作,很快就会忘记。过几天我会开始下一轮,希望今年6月之前能够拿到证。我的目标不仅仅是拿到这个证,更重要的是通过这个过程,能够掌握ES的方方面面,成为这方面的专家。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容