elasticsearch5.2搜索建议(自动补全)

问题描述

电商网站的搜索是最基础最重要的功能之一,搜索框上面的良好体验能为电商带来更高的收益,我们先来看看淘宝、京东、亚马逊网站的搜索建议。
在淘宝的搜索框输入【卫衣】时,下方的搜索建议包括建议词以及相关的标签:

Paste_Image.png

在京东的搜索框输入【卫衣】时,下方搜索建议右方显示建议词关联的商品数量:

Paste_Image.png

在亚马逊的搜索框输入【卫衣】时,搜索建议上部分能支持在特定的分类下进行搜索:

Paste_Image.png
通过上述对比可以看出,不同的电商对于搜索建议的侧重点略有不同,但核心的问题包括:
  1. 建议词的来源可以是商品的分类名称、品牌名称、商品属性、商品名称的高频词、热搜词,也可以是一些组合词,比如“分类 + 性别”和“分类 + 属性”,还可以是一些自定义添加的词;
  2. 建议词维护的时候需要考虑去重,比如“Nike”和“nike”应该是相同的;
关键词索引映射:
curl -XPUT http://192.168.138.210:9200/keyword/ -d'
{
    "settings" : {
        "analysis" : {
            "analyzer" : {
                "first_py_letter_analyzer" : {
                    "tokenizer" : "first_py_letter",
                    "filter":"edgeNGram_filter"
                },
                "full_pinyin_letter_analyzer" : {
                    "tokenizer" : "full_pinyin_letter",
                    "filter":"edgeNGram_filter"
                },
                "edgeNGram_analyzer":{
                    "tokenizer" : "edgeNGram_tokenizer"
                }
            },
            "tokenizer" : {
                "first_py_letter" : {
                    "type" : "pinyin",
                    "keep_first_letter" : true,
                    "keep_full_pinyin" : false,
                    "keep_original" : false,
                    "limit_first_letter_length" : 16,
                    "lowercase" : true,
                    "trim_whitespace" : true,
                    "keep_none_chinese_in_first_letter": false,
                    "none_chinese_pinyin_tokenize": false,
                    "keep_none_chinese": true,
                    "keep_none_chinese_in_joined_full_pinyin": true
                },
                "full_pinyin_letter" : {
                    "type": "pinyin",
                    "keep_separate_first_letter": false,
                    "keep_full_pinyin": false,
                    "keep_original": false,
                    "limit_first_letter_length": 16,
                    "lowercase": true,
                    "keep_first_letter": false,
                    "keep_none_chinese_in_first_letter": false,
                    "none_chinese_pinyin_tokenize": false,
                    "keep_none_chinese": true,
                    "keep_joined_full_pinyin": true,
                    "keep_none_chinese_in_joined_full_pinyin": true
                },
                "edgeNGram_tokenizer":{
                    "type": "edgeNGram",
                    "min_gram": 1,
                    "max_gram": 15,
                    "token_chars": ["letter", "digit"]
                }
            },
            "filter":{
                "edgeNGram_filter":{
                    "type": "edgeNGram",
                    "min_gram": 1,
                    "max_gram": 50,
                    "token_chars": ["letter", "digit"]
                }               
            }
        },
        "number_of_shards": 5,
        "number_of_replicas": 1
    },
    "mappings":{
        "suggestion":{
            "properties": {
                "keyword": {
                    "type": "keyword",
                    "fields": {
                        "keyword_ik": {
                            "type": "text",
                            "analyzer": "edgeNGram_analyzer"
                        },
                        "keyword_pinyin": {
                            "type": "text",
                            "analyzer": "full_pinyin_letter_analyzer"
                        },
                        "keyword_first_py": {
                            "type": "text",
                            "analyzer": "first_py_letter_analyzer"
                        }
                    }
                },              
                "count": {
                    "type": "long",
                    "index": "not_analyzed"
                },
                "weight": {
                    "type": "integer",
                    "index": "not_analyzed"
                }
            }
        }        
    }
}'

搜索语句:

{
    "sort": [
        {
            "weight": "desc"
        },
        {
            "count": "desc"
        },
        {
            "_score": "desc"
        }
    ],
    "query": {
        "dis_max": {
            "queries": [
                {
                    "match_phrase": {
                        "keyword.keyword_ik": {
                            "query": "卫衣"
                        }
                    }
                },
                {
                    "match_phrase": {
                        "keyword.keyword_pinyin": {
                            "query": "卫衣",
                            "boost": 2
                        }
                    }
                }
            ],
            "tie_breaker": 1
        }
    }
}

如果Elasticsearch返回的是空结果,此时应该需要增加拼写纠错的处理(拼写纠错也可以在调用Elasticsearch搜索的时候带上,但是通常情况下用户并没有拼写错误,所以建议还是在后面单独调用suggester);如果返回的suggest不为空,则根据新的词调用建议词服务;比如用户输入了【adidss】,调用Elasticsearch的suggester获取到的结果是【adidas】,则再根据adidas进行搜索建议词处理。

{
    "suggest": {
        "keyword_suggestion": {
            "text": "adidss",
            "phrase": {
                "field": "keyword.keyword_pinyin",
                "size": 1,
                "analyzer":"standard"
            }
        }
    }
}

关于排序:在我们的实现里面是通过weight和count进行排序的,weight目前只考虑了建议词的类型(比如分类 > 品牌 > 属性);

下面为测试数据:


Paste_Image.png

下面输入错误的关键词“adidss”,获得的结果是:


Paste_Image.png

到此搜索建议基本上完成,但我估计大家会有个疑惑,因为针对自动补全,elasticsearch 提供了 completion suggestion 来解决,但为什么我没用呢?主要是 completion suggestion 不支持按字段来排序,比如我这需求就是要按关键词权重(weight)和搜索次数(count)来排序的

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,421评论 25 707
  • 在基于Elasticsearch实现搜索建议一文中我们曾经介绍过如何基于Elasticsearch来实现搜索建议,...
    ginobefun阅读 17,153评论 2 48
  • 经常看到有人在讨论,婚姻是爱情的坟墓,进来的人想出去。可我进来了,就不想走了。 那是12年大学开始实...
    分必久何阅读 483评论 4 3
  • 有很多时候当我们遇到窘境或难题都会感觉困惑和焦虑。假如我们把它当做一个有型物体,处于困局的时候应该仅仅是看到这个物...
    泡泡里的鱼阅读 265评论 0 0
  • "我也不想说出那些让人难受的话,可是我控制不住我自己" 一直以来我都很关注一个话题,就是语言暴力。可能很多人不知道...
    林深见鹿723阅读 1,331评论 0 1