搜索引擎关键字智能提示的一种实现

背景

搜索关键字智能提示是一个搜索应用的标配,主要作用是避免用户输入错误的搜索词,并将用户引导到相应的关键词上,以提升用户搜索体验。

美团CRM系统中存在数以百万计的商家,为了让用户快速查找到目标商家,我们基于solrcloud实现了商家搜索模块。用户在查找商家时主要输入商户名、商户地址进行搜索,为了提升用户的搜索体验和输入效率,本文实现了一种基于solr前缀匹配查询关键字智能提示(Suggestion)实现。

需求分析

  • 支持前缀匹配原则 在搜索框中输入“海底”,搜索框下面会以海底为前缀,展示“海底捞”、“海底捞火锅”、“海底世界”等等搜索词;输入“万达”,会提示“万达影城”、“万达广场”、“万达百货”等搜索词。

  • 同时支持汉字、拼音输入 由于中文的特点,如果搜索自动提示可以支持拼音的话会给用户带来更大的方便,免得切换输入法。比如,输入“haidi”提示的关键字和输入“海底”提示的一样,输入“wanda”与输入“万达”提示的关键字一样。

  • 支持多音字输入提示 比如输入“chongqing”或者“zhongqing”都能提示出“重庆火锅”、“重庆烤鱼”、“重庆小天鹅”。

  • 支持拼音缩写输入 对于较长关键字,为了提高输入效率,有必要提供拼音缩写输入。比如输入“hd”应该能提示出“haidi”相似的关键字,输入“wd”也一样能提示出“万达”关键字。

  • 基于用户的历史搜索行为,按照关键字热度进行排序 为了提供suggest关键字的准确度,最终查询结果,根据用户查询关键字的频率进行排序,如输入[重庆,chongqing,cq,zhongqing,zq] —> [“重庆火锅”(f1),“重庆烤鱼”(f2),“重庆小天鹅”(f3),…],查询频率f1 > f2 > f3。

解决方案

  • 关键字收集 当用户输入一个前缀时,碰到提示的候选词很多的时候,如何取舍,哪些展示在前面,哪些展示在后面?这就是一个搜索热度的问题。用户在使用搜索引擎查找商家时,会输入大量的关键字,每一次输入就是对关键字的一次投票,那么关键字被输入的次数越多,它对应的查询就比较热门,所以需要把查询的关键字记录下来,并且统计出每个关键字的频率,方便提示结果按照频率排序。搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。

  • 汉字转拼音 用户输入的关键字可能是汉字、数字,英文,拼音,特殊字符等等,由于需要实现拼音提示,我们需要把汉字转换成拼音,java中考虑使用pinyin4j组件实现转换。

  • 拼音缩写提取 考虑到需要支持拼音缩写,汉字转换拼音的过程中,顺便提取出拼音缩写,如“chongqing”,“zhongqing”—>“cq”,”zq”。

  • 多音字全排列 要支持多音字提示,对查询串转换成拼音后,需要实现一个全排列组合,字符串多音字全排列算法如下:

    public static List getPermutationSentence(List > termArrays,int start) { if (CollectionUtils.isEmpty(termArrays)) return Collections.emptyList();

    int size = termArrays.size();
    if (start < 0 || start >= size) {return Collections.emptyList();
    }if (start == size-1) {return termArrays.get(start);
    }List<String> strings = termArrays.get(start);List<String> permutationSentences = getPermutationSentence(termArrays, start + 1);if (CollectionUtils.isEmpty(strings)) {return permutationSentences;
    }if (CollectionUtils.isEmpty(permutationSentences)) {return strings;
    }List<String> result = new ArrayList<String>();
    for (String pre : strings) {for (String suffix : permutationSentences) {result.add(pre+suffix);}
    }return result;
    

    }

  • 索引与前缀查询

方案一 Trie树 + TopK算法 Trie树即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。Trie是一颗存储多个字符串的树。相邻节点间的边代表一个字符,这样树的每条分支代表一则子串,而树的叶节点则代表完整的字符串。和普通树不同的地方是,相同的字符串前缀共享同一条分支。例如,给出一组单词inn, int, at, age, adv, ant, 我们可以得到下面的Trie: 美团前端架构

从上图可知,当用户输入前缀i的时候,搜索框可能会展示以i为前缀的“in”,“inn”,”int”等关键词,再当用户输入前缀a的时候,搜索框里面可能会提示以a为前缀的“ate”等关键词。如此,实现搜索引擎智能提示suggestion的第一个步骤便清晰了,即用trie树存储大量字符串,当前缀固定时,存储相对来说比较热的后缀。

TopK算法用于解决统计热词的问题。解决TopK问题主要有两种策略:hashMap统计+排序、堆排序 hashmap统计: 先对这批海量数据预处理。具体方法是:维护一个Key为Query字串,Value为该Query出现次数的HashTable,即hash_map(Query,Value),每次读取一个Query,如果该字串不在Table中,那么加入该字串,并且将Value值设为1;如果该字串在Table中,那么将该字串的计数加一即可,最终在O(N)的时间复杂度内用Hash表完成了统计。 堆排序:借助堆这个数据结构,找出Top K,时间复杂度为N‘logK。即借助堆结构,我们可以在log量级的时间内查找和调整/移动。因此,维护一个K(该题目中是10)大小的小根堆,然后遍历300万的Query,分别和根元素进行对比。所以,我们最终的时间复杂度是:O(N) + N’ * O(logK),(N为1000万,N’为300万)。

该方案存在的问题是: - 建索引和查询的时候都要把汉字转换成拼音,查询完成后还得把拼音转换成汉字显示,且需要考虑数字和特殊字符。 - 需要维护拼音、缩写两棵Trie树。

方案二 Solr自带Suggest智能提示 Solr作为一个应用广泛的搜索引擎系统,它内置了智能提示功能,叫做Suggest模块。该模块可选择基于提示词文本做智能提示,还支持通过针对索引的某个字段建立索引词库做智能提示。 (详见solr的wiki页面http://wiki.apache.org/solr/Suggester)

该方案存在的问题是: - 返回的结果是基于索引中字段的词频进行排序,不是用户搜索关键字的频率,因此不能将一些热门关键字排在前面。 - 拼音提示,多音字,缩写还是要另外加索引字段。

方案三 Solrcloud建立单独的collection,利用solr前缀查询实现 如前所述,以上两个方案在实施起来都存在一些问题,Trie树+TopK算法,在处理汉字suggest时不是很优雅,且需要维护两棵Trie树,实施起来比较复杂;Solr自带的suggest智能提示组件存在问题是使用freq排序算法,返回的结果完全基于索引中字符的出现次数,没有兼顾用户搜索词语的频率,因此无法将一些热门词排在更靠前的位置。于是,我们继续寻找一种解决这个问题更加优雅的方案。

至此,我们考虑专门为关键字建立一个索引collection,利用solr前缀查询实现。solr中的copyField能很好解决我们同时索引多个字段(汉字、pinyin, abbre)的需求,且field的multiValued属性设置为true时能解决同一个关键字的多音字组合问题。配置如下:

schema.xml:<field name="kw" type="string" indexed="true" stored="true" />  
<field name="pinyin" type="string" indexed="true" stored="false" multiValued="true"/>
<field name="abbre" type="string" indexed="true" stored="false" multiValued="true"/>
<field name="kwfreq" type="int" indexed="true" stored="true" />
<field name="_version_" type="long" indexed="true" stored="true"/>
<field name="suggest" type="suggest_text" indexed="true" stored="false" multiValued="true" />
------------------multiValued表示字段是多值的-------------------------------------
<uniqueKey>kw</uniqueKey>
<defaultSearchField>suggest</defaultSearchField>说明:
kw为原始关键字
pinyin和abbre的multiValued=true,在使用solrj建此索引时,定义成集合类型即可:如关键字“重庆”的pinyin字段为{chongqing,zhongqing}, abbre字段为{cq, zq}
kwfreq为用户搜索关键的频率,用于查询的时候排序-------------------------------------------------------<copyField source="kw" dest="suggest" />
<copyField source="pinyin" dest="suggest" />
<copyField source="abbre" dest="suggest" />------------------suggest_text----------------------------------<fieldType name="suggest_text" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true"><analyzer type="index"><tokenizer class="solr.KeywordTokenizerFactory" />&lt;filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true" /><filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" /><filter class="solr.LowerCaseFilterFactory" /><filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt" /></analyzer><analyzer type="query"><tokenizer class="solr.KeywordTokenizerFactory" /><filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" /><filter class="solr.LowerCaseFilterFactory" /><filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt" /></analyzer>
</fieldType>

KeywordTokenizerFactory:这个分词器不进行任何分词!整个字符流变为单个词元。String域类型也有类似的效果,但是它不能配置文本分析的其它处理组件,比如大小写转换。任何用于排序和大部分Faceting功能的索引域,这个索引域只有能一个原始域值中的一个词元。

前缀查询构造:

private SolrQuery getSuggestQuery(String prefix, Integer limit) {SolrQuery solrQuery = new SolrQuery();StringBuilder sb = new StringBuilder();sb.append(“suggest:").append(prefix).append("*");solrQuery.setQuery(sb.toString());solrQuery.addField("kw");solrQuery.addField("kwfreq");solrQuery.addSort("kwfreq", SolrQuery.ORDER.desc);solrQuery.setStart(0);solrQuery.setRows(limit);return solrQuery;
}

效果如下图所示: 美团前端架构

参考

  • 从Trie树谈到后缀树 http://blog.csdn.net/v_july_v/article/details/6897097
  • 搜索智能提示suggestion,附近地点搜索 http://blog.csdn.net/v_july_v/article/details/11288807
  • solr suggester http://wiki.apache.org/solr/Suggester

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/477829.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

会议交流 | DataFunSummit 知识图谱在线峰会——链接知识图谱最前沿技术和最落地产业化应用的桥梁!...

随着人工智能技术的发展与应用&#xff0c;知识图谱作为AI进步的阶梯越来越受到学术界和产业界的重视&#xff0c;并且已经在很多领域、场景中体现出自身的价值。从最初的互联网搜索、推荐、问答等ToC场景&#xff0c;逐渐进入到垂直行业ToB的应用当中。然而&#xff0c;场景的…

LeetCode 1209. 删除字符串中的所有相邻重复项 II(栈)

1. 题目 给你一个字符串 s&#xff0c;「k 倍重复项删除操作」将会从 s 中选择 k 个相邻且相等的字母&#xff0c;并删除它们&#xff0c;使被删去的字符串的左侧和右侧连在一起。 你需要对 s 重复进行无限次这样的删除操作&#xff0c;直到无法继续为止。 在执行完所有删除…

YUI经验谈 - 自定义事件默认行为

纵观主流JS库和框架&#xff0c;YUI在自定义事件方面做的尤为出色。如果需要挑出一个代表性的feature&#xff0c;那么非事件默认行为莫属。 是什么 YUI自定义事件在总体上模仿了DOM事件的设计思想。DOM中的一些事件是有默认行为的&#xff0c;详细见DOM3 Event - Default acti…

美团NLP中心算法实习生招聘

致力于连接最靠谱的算法岗与最强的求职者招聘贴投放请联系微信xixiaoyao-1岗位职责&#xff1a;NLP算法研发&#xff0c;例如文本挖掘、知识预训练、知识&多模态预训练等知识图谱构建核心技术相关论文撰写岗位要求&#xff1a;北京高校在校大学生。&#xff08;2023年毕业优…

论文浅尝 | 改善多语言KGQA的 Zero-shot 跨语言转换

笔记整理&#xff1a;谭亦鸣, 东南大学博士生来源&#xff1a;NAACL21链接&#xff1a;https://aclanthology.org/2021.naacl-main.465/概述为了扩展多语言知识图谱问答的应用&#xff0c;Zero-shot方法成为一个研究趋势。在Zero-shot的设定下&#xff0c;通过高资源语言的训练…

LeetCode 1172. 餐盘栈(栈 + set)

1. 题目 我们把无限数量 ∞ 的栈排成一行&#xff0c;按从左到右的次序从 0 开始编号。每个栈的的最大容量 capacity 都相同。 实现一个叫「餐盘」的类 DinnerPlates&#xff1a; DinnerPlates(int capacity) - 给出栈的最大容量 capacity。void push(int val) - 将给出的正…

Hive SQL的编译过程

Hive是基于Hadoop的一个数据仓库系统&#xff0c;在各大公司都有广泛的应用。美团数据仓库也是基于Hive搭建&#xff0c;每天执行近万次的Hive ETL计算流程&#xff0c;负责每天数百GB的数据存储和分析。Hive的稳定性和性能对我们的数据分析非常关键。 在几次升级Hive的过程中&…

Prompt tuning新工作,五个参数解决下游任务 fine-tuning

文 | 小伟编 | 小轶前言自从Google石破天惊地发布Bert以来&#xff0c;NLP就进入了预训练语言模型的时代。众所周知&#xff0c;我们可以用预训练语言模型来学习各种各样的任务&#xff0c;即使它们的特征空间有比较大的差异。那么预训练语言模型为什么会有这种泛化能力呢&…

会议交流 | 如何将图谱实体与关系更好的向量化,并基于推理扩充知识边界?——DataFun Summit2022知识图谱在线峰会...

背景介绍知识图谱是对人类先验知识的概括&#xff0c;具有重要的学术价值和广泛的应用前景。在深度学习广泛应用环境下&#xff0c;知识图谱的表示学习通过将图谱实体和关系向量化&#xff0c;便于利用深度学习技术实现异质信息融合&#xff1b;同时&#xff0c;基于这种图谱表…

真正的高阶特征交叉:xDeepFM与DCN-V2

文 | 水哥源 | 知乎Saying1. xDeepFM和DCN-V2是真正的高阶交叉&#xff0c;和前面讲的High Order Factorization Machine&#xff08;HOFM&#xff09;又有着千丝万缕的联系。某种简化下&#xff0c;都能退化为HOFM的形式2. 如图3. 推荐模型迭代的时候要平衡涨点和复杂度的关系…

学术会议 | 中国杭州举办——第21届国际语义网大会​ISWC2022 Call for Papers

中国杭州举办&#xff01;ISWC2022 Call for Papers.ISWC(International Semantic Web Conference)是语义网和知识图谱领域的国际顶级学术会议&#xff0c;2022年10月23-27日&#xff0c;ISWC将在中国杭州举行&#xff0c;通过线上线下结合的方式&#xff0c;汇聚全世界相关的科…

LeetCode 82. 删除排序链表中的重复元素 II(链表)

1. 题目 给定一个排序链表&#xff0c;删除所有含有重复数字的节点&#xff0c;只保留原始链表中 没有重复出现 的数字。 示例 1: 输入: 1->2->3->3->4->4->5 输出: 1->2->5示例 2: 输入: 1->1->1->2->3 输出: 2->3来源&#xff1a;力…

从 ACL’22 投稿情况,速览当下 NLP 研究热点!

文 | Yimin_饭煲编 | 小轶卖萌屋的作者们&#xff0c;最近可真是忙秃了头~&#xff0c;不仅要苦哈哈地赶 ACL 2022 提前了两个月的Deadline&#xff0c;还要尽心尽力为读者们提供高质量的内容。如果大家心疼卖萌屋的作者们的话&#xff0c;还请多多一键三连:)ACL2022 全部转向了…

开源开放 | DeepKE发布新版本:支持低资源、长篇章、多任务的图谱抽取开源框架(浙江大学)...

OpenKG地址&#xff1a;http://openkg.cn/tool/deepkeGitHub地址&#xff1a;https://github.com/zjunlp/deepkeGitee地址&#xff1a;https://gitee.com/openkg/deepkeDeepKE网站&#xff1a;http://deepke.zjukg.org/CN/index.html开放许可协议&#xff1a;GPL 3.0贡献者&…

LeetCode 478. 在圆内随机生成点(概率)

1. 题目 给定圆的半径和圆心的 x、y 坐标&#xff0c;写一个在圆中产生均匀随机点的函数 randPoint 。 说明: 输入值和输出值都将是浮点数。圆的半径和圆心的 x、y 坐标将作为参数传递给类的构造函数。圆周上的点也认为是在圆中。randPoint 返回一个包含随机点的x坐标和y坐标…

11月AI大事件回顾:GPT3开放使用/女娲视觉大模型/AE文艺复兴/...

编 | iven感谢提供本期内容的 ZenMoore、 jxyxiangyu、付瑶大家好&#xff5e; 11月的新闻速报来啦&#xff01;上个月不知道大家有没有忙着写文章&#xff0c;反正小编是这样的&#xff1a;好啦&#xff0c;让我们快来回顾上个月的 AI 大新闻吧&#xff01;学术进展何恺明 Mas…

开源开放 | 开源立体化漏洞情报知识图谱(四维创智)

OpenKG地址&#xff1a;http://openkg.cn/dataset/vuln-sprocket开放许可协议&#xff1a;CC BY-SA 4.0 &#xff08;署名相似共享&#xff09;贡献者&#xff1a;四维创智&#xff08;李德斌&#xff0c;孙基栩&#xff0c;鲍晨阳&#xff09;1. 前言随着时间的推移&#xff0…

LeetCode 515. 在每个树行中找最大值(层序遍历)

1. 题目 您需要在二叉树的每一行中找到最大的值。 示例&#xff1a; 输入: 1/ \3 2/ \ \ 5 3 9 输出: [1, 3, 9]来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode-cn.com/problems/find-largest-value-in-each-tree-row 著作…

GBDT是如何成为推荐系统顶级工具人的?

文 | 水哥源 | 知乎Saying1. 集成学习的ensemble注意一定要读作昂三姆包而不是印三姆包&#xff0c;一天一个算法工程师装x小技巧2. 区别bagging和boosting的准则是&#xff0c;先训练的模型对于后训练的模型是否有影响3. GBDT中&#xff0c;B&#xff08;boosting&#xff09;…

会议交流 | 如何提升推荐系统的可解释性?——DataFunSummit2022知识图谱在线峰会...

背景介绍知识图谱及特征学习结合智能推荐&#xff0c;可解决数据稀疏性及冷启动问题&#xff0c;更好的提升推荐决策场的准确性、多样性及可解释性&#xff0c;进而提升各个场景的推荐决策效率和体验。3月12日13:30-16:50&#xff0c;在DataFunSummit2022&#xff1a;知识图谱在…