国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

站長(zhǎng)之家,中國(guó)草根站長(zhǎng)新聞、建站經(jīng)驗(yàn)、素材資源交流平臺(tái)!
分類(lèi)導(dǎo)航

站長(zhǎng)新聞|網(wǎng)站運(yùn)營(yíng)|建站經(jīng)驗(yàn)|網(wǎng)站優(yōu)化|站長(zhǎng)資源|站長(zhǎng)源碼|

服務(wù)器之家 - 站長(zhǎng)之家 - 建站經(jīng)驗(yàn) - 詳解美團(tuán)實(shí)現(xiàn)搜索關(guān)鍵詞自動(dòng)匹配功能的方法

詳解美團(tuán)實(shí)現(xiàn)搜索關(guān)鍵詞自動(dòng)匹配功能的方法

2020-05-31 17:00美團(tuán)點(diǎn)評(píng)技術(shù)團(tuán)隊(duì)佚名 建站經(jīng)驗(yàn)

這篇文章主要介紹了美團(tuán)實(shí)現(xiàn)搜索關(guān)鍵詞自動(dòng)匹配功能的方法,講到了很多對(duì)多音字和拼音等實(shí)際問(wèn)題的解決,需要的朋友可以參考下

問(wèn)題背景
搜索關(guān)鍵字智能提示是一個(gè)搜索應(yīng)用的標(biāo)配,主要作用是避免用戶輸入錯(cuò)誤的搜索詞,并將用戶引導(dǎo)到相應(yīng)的關(guān)鍵詞上,以提升用戶搜索體驗(yàn)。

美團(tuán)CRM系統(tǒng)中存在數(shù)以百萬(wàn)計(jì)的商家,為了讓用戶快速查找到目標(biāo)商家,我們基于solrcloud實(shí)現(xiàn)了商家搜索模塊。用戶在查找商家時(shí)主要輸入商戶名、商戶地址進(jìn)行搜索,為了提升用戶的搜索體驗(yàn)和輸入效率,本文實(shí)現(xiàn)了一種基于solr前綴匹配查詢(xún)關(guān)鍵字智能提示(Suggestion)實(shí)現(xiàn)。

需求分析
1.支持前綴匹配原則

在搜索框中輸入“海底”,搜索框下面會(huì)以海底為前綴,展示“海底撈”、“海底撈火鍋”、“海底世界”等等搜索詞;輸入“萬(wàn)達(dá)”,會(huì)提示“萬(wàn)達(dá)影城”、“萬(wàn)達(dá)廣場(chǎng)”、“萬(wàn)達(dá)百貨”等搜索詞。
2.同時(shí)支持漢字、拼音輸入
由于中文的特點(diǎn),如果搜索自動(dòng)提示可以支持拼音的話會(huì)給用戶帶來(lái)更大的方便,免得切換輸入法。比如,輸入“haidi”提示的關(guān)鍵字和輸入“海底”提示的一樣,輸入“wanda”與輸入“萬(wàn)達(dá)”提示的關(guān)鍵字一樣。
3.支持多音字輸入提示
比如輸入“chongqing”或者“zhongqing”都能提示出“重慶火鍋”、“重慶烤魚(yú)”、“重慶小天鵝”。
4.支持拼音縮寫(xiě)輸入
對(duì)于較長(zhǎng)關(guān)鍵字,為了提高輸入效率,有必要提供拼音縮寫(xiě)輸入。比如輸入“hd”應(yīng)該能提示出“haidi”相似的關(guān)鍵字,輸入“wd”也一樣能提示出“萬(wàn)達(dá)”關(guān)鍵字。
基于用戶的歷史搜索行為,按照關(guān)鍵字熱度進(jìn)行排序
為了提供suggest關(guān)鍵字的準(zhǔn)確度,最終查詢(xún)結(jié)果,根據(jù)用戶查詢(xún)關(guān)鍵字的頻率進(jìn)行排序,如輸入[重慶,chongqing,cq,zhongqing,zq] —> [“重慶火鍋”(f1),“重慶烤魚(yú)”(f2),“重慶小天鵝”(f3),…],查詢(xún)頻率f1 > f2 > f3。


解決方案
1.關(guān)鍵字收集

當(dāng)用戶輸入一個(gè)前綴時(shí),碰到提示的候選詞很多的時(shí)候,如何取舍,哪些展示在前面,哪些展示在后面?這就是一個(gè)搜索熱度的問(wèn)題。用戶在使用搜索引擎查找商家時(shí),會(huì)輸入大量的關(guān)鍵字,每一次輸入就是對(duì)關(guān)鍵字的一次投票,那么關(guān)鍵字被輸入的次數(shù)越多,它對(duì)應(yīng)的查詢(xún)就比較熱門(mén),所以需要把查詢(xún)的關(guān)鍵字記錄下來(lái),并且統(tǒng)計(jì)出每個(gè)關(guān)鍵字的頻率,方便提示結(jié)果按照頻率排序。搜索引擎會(huì)通過(guò)日志文件把用戶每次檢索使用的所有檢索串都記錄下來(lái),每個(gè)查詢(xún)串的長(zhǎng)度為1-255字節(jié)。
2.漢字轉(zhuǎn)拼音
用戶輸入的關(guān)鍵字可能是漢字、數(shù)字,英文,拼音,特殊字符等等,由于需要實(shí)現(xiàn)拼音提示,我們需要把漢字轉(zhuǎn)換成拼音,java中考慮使用pinyin4j組件實(shí)現(xiàn)轉(zhuǎn)換。
3.拼音縮寫(xiě)提取
考慮到需要支持拼音縮寫(xiě),漢字轉(zhuǎn)換拼音的過(guò)程中,順便提取出拼音縮寫(xiě),如“chongqing”,"zhongqing"--->"cq",”zq”。
4.多音字全排列
要支持多音字提示,對(duì)查詢(xún)串轉(zhuǎn)換成拼音后,需要實(shí)現(xiàn)一個(gè)全排列組合,字符串多音字全排列算法如下:

Java Code復(fù)制內(nèi)容到剪貼板
  1. public static List getPermutationSentence(List> termArrays,int start) {   

  2.   

  3.   if (CollectionUtils.isEmpty(termArrays))   

  4.       return Collections.emptyList();   

  5.   

  6.   int size = termArrays.size();   

  7.   if (start < 0 || start >= size) {   

  8.       return Collections.emptyList();   

  9.   }   

  10.   

  11.   if (start == size-1) {   

  12.       return termArrays.get(start);   

  13.   }   

  14.   

  15.   List<String> strings = termArrays.get(start);   

  16.   

  17.   List<String> permutationSentences = getPermutationSentence(termArrays, start + 1);   

  18.   

  19.   if (CollectionUtils.isEmpty(strings)) {   

  20.       return permutationSentences;   

  21.   }   

  22.   

  23.   if (CollectionUtils.isEmpty(permutationSentences)) {   

  24.       return strings;   

  25.   }   

  26.   

  27.   List<String> result = new ArrayList<String>();   

  28.   for (String pre : strings) {   

  29.       for (String suffix : permutationSentences) {   

  30.           result.add(pre+suffix);   

  31.       }   

  32.   }   

  33.   

  34.   return result;   

  35. }  

 

索引與前綴查詢(xún)
方案一 Trie樹(shù) + TopK算法

Trie樹(shù)即字典樹(shù),又稱(chēng)單詞查找樹(shù)或鍵樹(shù),是一種樹(shù)形結(jié)構(gòu),是一種哈希樹(shù)的變種。典型應(yīng)用是用于統(tǒng)計(jì)和排序大量的字符串(但不僅限于字符串),所以經(jīng)常被搜索引擎系統(tǒng)用于文本詞頻統(tǒng)計(jì)。它的優(yōu)點(diǎn)是:最大限度地減少無(wú)謂的字符串比較,查詢(xún)效率比哈希表高。Trie是一顆存儲(chǔ)多個(gè)字符串的樹(shù)。相鄰節(jié)點(diǎn)間的邊代表一個(gè)字符,這樣樹(shù)的每條分支代表一則子串,而樹(shù)的葉節(jié)點(diǎn)則代表完整的字符串。和普通樹(shù)不同的地方是,相同的字符串前綴共享同一條分支。例如,給出一組單詞inn, int, at, age, adv, ant, 我們可以得到下面的Trie:
詳解美團(tuán)實(shí)現(xiàn)搜索關(guān)鍵詞自動(dòng)匹配功能的方法

從上圖可知,當(dāng)用戶輸入前綴i的時(shí)候,搜索框可能會(huì)展示以i為前綴的“in”,“inn”,”int"等關(guān)鍵詞,再當(dāng)用戶輸入前綴a的時(shí)候,搜索框里面可能會(huì)提示以a為前綴的“ate”等關(guān)鍵詞。如此,實(shí)現(xiàn)搜索引擎智能提示suggestion的第一個(gè)步驟便清晰了,即用trie樹(shù)存儲(chǔ)大量字符串,當(dāng)前綴固定時(shí),存儲(chǔ)相對(duì)來(lái)說(shuō)比較熱的后綴。

TopK算法用于解決統(tǒng)計(jì)熱詞的問(wèn)題。解決TopK問(wèn)題主要有兩種策略:hashMap統(tǒng)計(jì)+排序、堆排序
hashmap統(tǒng)計(jì): 先對(duì)這批海量數(shù)據(jù)預(yù)處理。具體方法是:維護(hù)一個(gè)Key為Query字串,Value為該Query出現(xiàn)次數(shù)的HashTable,即hash_map(Query,Value),每次讀取一個(gè)Query,如果該字串不在Table中,那么加入該字串,并且將Value值設(shè)為1;如果該字串在Table中,那么將該字串的計(jì)數(shù)加一即可,最終在O(N)的時(shí)間復(fù)雜度內(nèi)用Hash表完成了統(tǒng)計(jì)。
堆排序:借助堆這個(gè)數(shù)據(jù)結(jié)構(gòu),找出Top K,時(shí)間復(fù)雜度為N‘logK。即借助堆結(jié)構(gòu),我們可以在log量級(jí)的時(shí)間內(nèi)查找和調(diào)整/移動(dòng)。因此,維護(hù)一個(gè)K(該題目中是10)大小的小根堆,然后遍歷300萬(wàn)的Query,分別和根元素進(jìn)行對(duì)比。所以,我們最終的時(shí)間復(fù)雜度是:O(N) + N' * O(logK),(N為1000萬(wàn),N’為300萬(wàn))。

該方案存在的問(wèn)題是:

建索引和查詢(xún)的時(shí)候都要把漢字轉(zhuǎn)換成拼音,查詢(xún)完成后還得把拼音轉(zhuǎn)換成漢字顯示,且需要考慮數(shù)字和特殊字符。
需要維護(hù)拼音、縮寫(xiě)兩棵Trie樹(shù)。


方案二 Solr自帶Suggest智能提示
Solr作為一個(gè)應(yīng)用廣泛的搜索引擎系統(tǒng),它內(nèi)置了智能提示功能,叫做Suggest模塊。該模塊可選擇基于提示詞文本做智能提示,還支持通過(guò)針對(duì)索引的某個(gè)字段建立索引詞庫(kù)做智能提示。 (詳見(jiàn)solr的wiki頁(yè)面http://wiki.apache.org/solr/Suggester)

該方案存在的問(wèn)題是:

返回的結(jié)果是基于索引中字段的詞頻進(jìn)行排序,不是用戶搜索關(guān)鍵字的頻率,因此不能將一些熱門(mén)關(guān)鍵字排在前面。
拼音提示,多音字,縮寫(xiě)還是要另外加索引字段。


方案三 Solrcloud建立單獨(dú)的collection,利用solr前綴查詢(xún)實(shí)現(xiàn)
如前所述,以上兩個(gè)方案在實(shí)施起來(lái)都存在一些問(wèn)題,Trie樹(shù)+TopK算法,在處理漢字suggest時(shí)不是很優(yōu)雅,且需要維護(hù)兩棵Trie樹(shù),實(shí)施起來(lái)比較復(fù)雜;Solr自帶的suggest智能提示組件存在問(wèn)題是使用freq排序算法,返回的結(jié)果完全基于索引中字符的出現(xiàn)次數(shù),沒(méi)有兼顧用戶搜索詞語(yǔ)的頻率,因此無(wú)法將一些熱門(mén)詞排在更靠前的位置。于是,我們繼續(xù)尋找一種解決這個(gè)問(wèn)題更加優(yōu)雅的方案。

至此,我們考慮專(zhuān)門(mén)為關(guān)鍵字建立一個(gè)索引collection,利用solr前綴查詢(xún)實(shí)現(xiàn)。solr中的copyField能很好解決我們同時(shí)索引多個(gè)字段(漢字、pinyin, abbre)的需求,且field的multiValued屬性設(shè)置為true時(shí)能解決同一個(gè)關(guān)鍵字的多音字組合問(wèn)題。配置如下:

schema.xml:

XML/HTML Code復(fù)制內(nèi)容到剪貼板
  1. <field name="kw" type="string" indexed="true" stored="true" />     

  2. <field name="pinyin" type="string" indexed="true" stored="false" multiValued="true"/>  

  3. <field name="abbre" type="string" indexed="true" stored="false" multiValued="true"/>  

  4. <field name="kwfreq" type="int" indexed="true" stored="true" />  

  5. <field name="_version_" type="long" indexed="true" stored="true"/>  

  6. <field name="suggest" type="suggest_text" indexed="true" stored="false" multiValued="true" />  

------------------multiValued表示字段是多值的-------------------------------------

XML/HTML Code復(fù)制內(nèi)容到剪貼板
  1. <uniqueKey>kw</uniqueKey>  

  2. <defaultSearchField>suggest</defaultSearchField>  

說(shuō)明:
kw為原始關(guān)鍵字
pinyin和abbre的multiValued=true,在使用solrj建此索引時(shí),定義成集合類(lèi)型即可:如關(guān)鍵字“重慶”的pinyin字段為{chongqing,zhongqing}, abbre字段為{cq, zq}
kwfreq為用戶搜索關(guān)鍵的頻率,用于查詢(xún)的時(shí)候排序

-------------------------------------------------------

XML/HTML Code復(fù)制內(nèi)容到剪貼板
  1. <copyField source="kw" dest="suggest" />  

  2. <copyField source="pinyin" dest="suggest" />  

  3. <copyField source="abbre" dest="suggest" />  

------------------suggest_text----------------------------------

XML/HTML Code復(fù)制內(nèi)容到剪貼板
  1. <fieldType name="suggest_text" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">  

  2.     <analyzer type="index">  

  3.             <tokenizer class="solr.KeywordTokenizerFactory" />  

  4.             <filter class="solr.SynonymFilterFactory"    

  5.                     synonyms="synonyms.txt"    

  6.                     ignoreCase="true"    

  7.                     expand="true" />  

  8.             <filter class="solr.StopFilterFactory"    

  9.                     ignoreCase="true"    

  10.                     words="stopwords.txt"    

  11.                     enablePositionIncrements="true" />  

  12.             <filter class="solr.LowerCaseFilterFactory" />  

  13.             <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt" />  

  14.     </analyzer>  

  15.     <analyzer type="query">  

  16.             <tokenizer class="solr.KeywordTokenizerFactory" />  

  17.             <filter class="solr.StopFilterFactory"    

  18.                     ignoreCase="true"    

  19.                     words="stopwords.txt"    

  20.                     enablePositionIncrements="true" />  

  21.             <filter class="solr.LowerCaseFilterFactory" />  

  22.             <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt" />  

  23.     </analyzer>  

  24. </fieldType>  

KeywordTokenizerFactory:這個(gè)分詞器不進(jìn)行任何分詞!整個(gè)字符流變?yōu)閱蝹€(gè)詞元。String域類(lèi)型也有類(lèi)似的效果,但是它不能配置文本分析的其它處理組件,比如大小寫(xiě)轉(zhuǎn)換。任何用于排序和大部分Faceting功能的索引域,這個(gè)索引域只有能一個(gè)原始域值中的一個(gè)詞元。

前綴查詢(xún)構(gòu)造:

Java Code復(fù)制內(nèi)容到剪貼板
  1. private SolrQuery getSuggestQuery(String prefix, Integer limit) {   

  2.     SolrQuery solrQuery = new SolrQuery();   

  3.     StringBuilder sb = new StringBuilder();   

  4.     sb.append(“suggest:").append(prefix).append("*");

  5.     solrQuery.setQuery(sb.toString());  

  6.     solrQuery.addField("kw");  

  7.     solrQuery.addField("kwfreq");  

  8.     solrQuery.addSort("kwfreq", SolrQuery.ORDER.desc);   

  9.     solrQuery.setStart(0);   

  10.     solrQuery.setRows(limit);   

  11.     return solrQuery;   

  12. }  

效果如下圖所示:
詳解美團(tuán)實(shí)現(xiàn)搜索關(guān)鍵詞自動(dòng)匹配功能的方法

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: av一区二区在线观看 | 欧美一区二区在线 | 国产高清av在线一区二区三区 | 久久香视频 | 综合久久精品 | 久久av一区 | 在线91| av天天看 | 欧美黄色一级片免费看 | 中文字幕在线三区 | 视频一区中文字幕 | 欧美日韩三区 | 狠狠操狠狠干 | 成人av福利| 欧美疯狂性受xxxxx另类 | 夜夜夜久久久 | 都市激情在线视频 | 精品久久国产老人久久综合 | 亚洲精品电影在线观看 | 另类久久 | 欧美区国产 | 91一区二区在线 | av中文字幕在线观看 | 国产色视频| 日韩欧美在线观看 | 这里只有精品国产 | 深夜精品 | 成人片在线播放 | 日韩成人片 | 午夜私人影院 | 久久国产精品久久久久久 | 欧美精品一区二区三区在线四季 | 日韩和的一区二在线 | 日本不卡高字幕在线2019 | 国产在线观看一区二区三区 | 亚洲精品乱码久久久久久麻豆不卡 | 欧美日韩精品电影 | 国产成人一区二区三区 | 可以免费看黄的网站 | 草久在线观看 | 黄色毛片一级片 |