设计方案Elasticsearch

模拟实战京东搜索效果(一)

2020-04-14  本文已影响0人  响指_郭彦超

搜索是很多内容类app必不可少的功能,而搜索框提示则为用户关键词输入提供了一种引导,一个友好的搜索框提示不仅能提升用户体验,还能帮助用户节省触达商品的时间提升搜索效率。

image.png image.png image.png

搜索框功能主要有3部分组成:

实现流程

ES官方文档建议通过phrase Suggester实行搜索框的自动补全,但这种查询对中文支持不太友好,经常会不做提示;下面我们通过n-gram来实现符合中国人民使用习惯的提示框。

假设有一个词hello,普通建索引时,就是把这个词hello放入倒排索引
用户输入h、he时会找不到索引(倒排索引中只有hello),因此匹配失败
而对于输入即搜索这种应用场景,可以使用一种特殊的n-gram,称为边界n-grams (edge n-grams)
所谓的edge n-gram,就是指它会固定从一边开始,进行窗口滑动,每次滑动长度为1,最终的结果取决于 n 的选择长度
以单词hello为例,它的edge n-gram的结果如下:

h
he
hel
hell
hello

因此可以发现到,在使用edge n-gram建索引时,一个单词会生成好几个索引,而这些索引一定是从头开始
这符合了输入即搜索的特性,即是用户打h、he能找到倒排中的索引h、he,而这些索引对应著的数据就是hello

依赖插件:

构建索引库:

PUT st
{
  
    "mappings" : {
      "dynamic" : "false",
      "properties" : {
        "suggest" : {
          "type" : "text",
          "analyzer" : "autocomplete" ,
          "search_analyzer": "autocomplete_search"
        },
        "weight" : {
          "type" : "integer"
        },
        "count" : {
          "type" : "integer"
        }
      }
    },
    "settings" : {
      "index" : {
        "number_of_shards" : "1",
        "analysis" : {
          "filter" : {
            "length_filter" : {
              "type" : "length",
              "min" : "2"
            },
            "my_pinyin" : {
              "keep_joined_full_pinyin" : "true",
              "lowercase" : "true",
              "keep_original" : "true",
              "remove_duplicated_term" : "true",
              "keep_separate_first_letter" : "false",
              "type" : "pinyin",
              "limit_first_letter_length" : "16",
              "keep_full_pinyin" : "true"
            }
          },
          "analyzer" : {
            "autocomplete_search" : {
              "filter" : [
                "lowercase"
              ],
              "tokenizer" : "search_py"
            },
            "autocomplete" : {
              "filter" : [
                "lowercase",
                "length_filter",
                "my_pinyin"
              ],
              "tokenizer" : "autocomplete"
            } 
          },
          "tokenizer" : {
            "autocomplete" : {
               
              "min_gram" : "2",
              "type" : "edge_ngram",
              "max_gram" : "16"
            } ,
            "search_py" : {
              "keep_joined_full_pinyin" : "true",
              "keep_none_chinese_in_first_letter " : "true",
              "lowercase" : "true",
              "none_chinese_pinyin_tokenize" : "false",
              "keep_none_chinese_in_joined_full_pinyin" : "true",
              "keep_original" : "true",
              "keep_first_letter" : "true",
              "keep_separate_first_letter" : "false",
              "type" : "pinyin",
              "limit_first_letter_length" : "16",
              "keep_full_pinyin" : "false"
            }
          }
        },
        "number_of_replicas" : "1" 
      }
    }
}

Mapping
Setting
keep_first_letter:这个参数会将词的第一个字母全部拼起来.例如:刘德华->ldh.默认为:true
keep_separate_first_letter:这个会将第一个字母一个个分开.例如:刘德华->l,d,h.默认为:flase.如果开启,可能导致查询结果太过于模糊,准确率太低.
limit_first_letter_length:设置最大keep_first_letter结果的长度,默认为:16
keep_full_pinyin:如果打开,它将保存词的全拼,并按字分开保存.例如:刘德华> [liu,de,hua],默认为:true
keep_joined_full_pinyin:如果打开将保存词的全拼.例如:刘德华> [liudehua],默认为:false
keep_none_chinese:将非中文字母或数字保留在结果中.默认为:true
keep_none_chinese_together:保证非中文在一起.默认为: true, 例如: DJ音乐家 -> DJ,yin,yue,jia, 如果设置为:false, 例如: DJ音乐家 -> D,J,yin,yue,jia, 注意: keep_none_chinese应该先开启.
keep_none_chinese_in_first_letter:将非中文字母保留在首字母中.例如: 刘德华AT2016->ldhat2016, 默认为:true
keep_none_chinese_in_joined_full_pinyin:将非中文字母保留为完整拼音. 例如: 刘德华2016->liudehua2016, 默认为: false
none_chinese_pinyin_tokenize:如果他们是拼音,切分非中文成单独的拼音项. 默认为:true,例如: liudehuaalibaba13zhuanghan -> liu,de,hua,a,li,ba,ba,13,zhuang,han, 注意: keep_none_chinese和keep_none_chinese_together需要先开启.
keep_original:是否保持原词.默认为:false
lowercase:小写非中文字母.默认为:true
trim_whitespace:去掉空格.默认为:true
remove_duplicated_term:保存索引时删除重复的词语.例如: de的>de, 默认为: false, 注意:开启可能会影响位置相关的查询.
ignore_pinyin_offset:在6.0之后,严格限制偏移量,不允许使用重叠的标记.使用此参数时,忽略偏移量将允许使用重叠的标记.请注意,所有与位置相关的查询或突出显示都将变为错误,您应使用多个字段并为不同的字段指定不同的设置查询目的.如果需要偏移量,请将其设置为false。默认值:true

插入测试数据

curl -XPUT "http://1.0.0.1:9200/st/_doc/1" -H 'Content-Type: application/json' -d'{   "suggest": "小米手机",  "count":110,"weight":10}'

curl -XPUT "http://1.0.0.1:9200/st/_doc/2" -H 'Content-Type: application/json' -d'{   "suggest": "小米手机新款",  "count":110,"weight":8}'

curl -XPUT "http://1.0.0.1:9200/st/_doc/3" -H 'Content-Type: application/json' -d'{   "suggest": "小米手机 5g",  "count":110,"weight":10}'

curl -XPUT "http://1.0.0.1:9200/st/_doc/4" -H 'Content-Type: application/json' -d'{   "suggest": "小米128g",  "count":110,"weight":6}'

curl -XPUT "http://1.0.0.1:9200/st/_doc/5" -H 'Content-Type: application/json' -d'{   "suggest": "小米袋装",  "count":110,"weight":6}'

curl -XPUT "http://1.0.0.1:9200/st/_doc/6" -H 'Content-Type: application/json' -d'{   "suggest": "华为5g新款",  "count":110,"weight":10}'

curl -XPUT "http://1.0.0.1:9200/st/_doc/7" -H 'Content-Type: application/json' -d'{   "suggest": "华为手机",  "count":110,  "weight":10}'

curl -XPUT "http://1.0.0.1:9200/st/_doc/8" -H 'Content-Type: application/json' -d'{   "suggest": "小蜜蜂", "count":110, "weight":8}'

权重计算

关联商品数量

定期修正

自动补全效果展示

GET st/_search
{
  "sort": [
    {
      "weight": {
        "order": "desc"
      }
    }
  ], 
  "query": {
        "multi_match": {
          "query": "小米sj",
          "fuzziness": 1,
          "prefix_length" : 1,
          "fields": ["suggest"]
        }
      }

}

需要注意的是,这里使用fuzziness来模糊匹配提升用户体验,fuzziness=1 允许用户输入一个错别字,并通过prefix_length设置为1来跳过开头首个字符的判断,因为一般用户输入出错大多发生在后面

{
        "_index" : "st",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : null,
        "_source" : {
          "suggest" : "小米手机",
          "count" : 110,
          "weight" : 10
        },
        "sort" : [
          10
        ]
      },
      {
        "_index" : "st",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : null,
        "_source" : {
          "suggest" : "小米手机新款",
          "count" : 110,
          "weight" : 8
        },
        "sort" : [
          8
        ]
      }

智能纠错效果展示

GET st/_search
{
  "_source": false, 
  "size": 0, 
  "suggest": { 
    "term-suggestion": {
      "text": "小密",
     "term": {
       "field": "suggest",
       "min_word_length":2, 
       "prefix_length":1,
       “min_doc_freq”:2,
       "size":2
     }
    }
  }
}

需要注意:
其中min_word_length是用来控制候选词长度的,这里设置为2,意思是当term长度>=2才会被显示;
prefix_length=1表示忽略首字符是错别字,大多数输入错别字发生在后面;
min_doc_freq 当建议词出现文档频率低于该值时将被忽略,线上可适当调大该值以提升搜索效果

{
        "text" : "小密",
        "offset" : 0,
        "length" : 0,
        "options" : [
          {
            "text" : "小米",
            "score" : 0.5,
            "freq" : 5
          },
          {
            "text" : "小蜜",
            "score" : 0.5,
            "freq" : 1
          }
        ]
      }

线上效果

易企秀商城

上一篇 下一篇

猜你喜欢

热点阅读