許祥,余立毅
(景德鎮(zhèn)陶瓷大學(xué)信息工程學(xué)院,景德鎮(zhèn)333403)
Solr;Lucene;商品搜索;HanLP;布隆過(guò)濾器
網(wǎng)絡(luò)購(gòu)物已經(jīng)成為了人們?nèi)粘5南M(fèi)習(xí)慣,在這些購(gòu)物應(yīng)用中,產(chǎn)品搜索是它們的必備功能,搜索能夠幫助用戶(hù)更快更準(zhǔn)確地找到自己需要的物品,保障購(gòu)物體驗(yàn)。Solr是一個(gè)獨(dú)立的企業(yè)級(jí)搜索引擎服務(wù)器,它是以Lucene全文檢索技術(shù)為基礎(chǔ)構(gòu)建的Web應(yīng)用,能夠快速地提供檢索服務(wù)。Lucene是一個(gè)成熟的信息檢索程序庫(kù),它在全文檢索領(lǐng)域、文本相似度計(jì)算領(lǐng)域以及構(gòu)建搜索引擎方面都有廣泛的應(yīng)用。由于使用傳統(tǒng)數(shù)據(jù)庫(kù)的應(yīng)用系統(tǒng)在商品搜索效率和結(jié)果上都無(wú)法滿(mǎn)足日益增長(zhǎng)的數(shù)據(jù)訪問(wèn)量,因此針對(duì)商品搜索所需要的快速、精準(zhǔn)、高效的設(shè)計(jì)需求,通過(guò)對(duì)全文檢索[1-4]尤其是垂直搜索技術(shù)[5-6]的研究,利用關(guān)鍵詞過(guò)濾、中文分詞器和改進(jìn)商品默認(rèn)排序,實(shí)現(xiàn)一個(gè)能夠滿(mǎn)足小型商品搜索的通用化引擎。
本文利用Solr將商品數(shù)據(jù)庫(kù)中的數(shù)據(jù)進(jìn)行索引,構(gòu)建索引庫(kù),搭建初始Web應(yīng)用系統(tǒng)。使用布隆過(guò)濾器減少直接查找索引庫(kù)的索引詞次數(shù),優(yōu)化索引效率。根據(jù)設(shè)計(jì)需求修改Lucene的排序[7-8]機(jī)制,簡(jiǎn)化內(nèi)部搜索過(guò)程,自定義商品排序,進(jìn)一步加快檢索速度。在最后的實(shí)驗(yàn)環(huán)節(jié),系統(tǒng)能夠快速地提供商品搜索服務(wù),取得了不錯(cuò)的效果。
布隆過(guò)濾器(Bloom Filter)[9]是1970年由布隆提出的。它實(shí)際上是一個(gè)很長(zhǎng)的二進(jìn)制向量bitarray和一系列隨機(jī)映射函數(shù)Hash,用于解決單個(gè)Hash的沖突問(wèn)題。假設(shè)一種bitarray長(zhǎng)度為m,有k個(gè)哈希函數(shù),且每個(gè)哈希函數(shù)的輸出范圍都大于m,接著將輸出值對(duì)m取余(%m),就會(huì)得到k個(gè)[0,m-1]的值,由于每個(gè)哈希函數(shù)之間相互獨(dú)立,因此這k個(gè)數(shù)也相互獨(dú)立,最后將這k個(gè)數(shù)對(duì)應(yīng)到bitarray上并標(biāo)記為1。等判斷時(shí),將輸入對(duì)象經(jīng)過(guò)這k個(gè)哈希函數(shù)計(jì)算得到k個(gè)值,然后判斷對(duì)應(yīng)bitarray的k個(gè)位置是否都為1,如果有一個(gè)不為1,那么這個(gè)輸入對(duì)象則不在這個(gè)集合中;如果都是1,那說(shuō)明在集合中,但有可能會(huì)誤,由于當(dāng)輸入對(duì)象過(guò)多,而集合也就是bitarray過(guò)小,則會(huì)出現(xiàn)大部分為1的情況,那樣就容易發(fā)生誤判。所以它的優(yōu)點(diǎn)是空間效率和查詢(xún)時(shí)間都比一般的算法要好的多,缺點(diǎn)是有一定的誤識(shí)別率和刪除困難。
假設(shè)輸入對(duì)象個(gè)數(shù)為n,bitarray大?。ㄒ簿褪遣悸∵^(guò)濾器大?。閙,所容忍的誤判率p和哈希函數(shù)的個(gè)數(shù)k。計(jì)算公式如下:
使用布隆過(guò)濾器預(yù)先判斷單詞是不是在該索引庫(kù)里。在系統(tǒng)啟動(dòng)之后,讀取Lucene索引庫(kù)中的所有詞條,將它們加載進(jìn)布隆過(guò)濾器對(duì)象中,完成BloomFilter對(duì)象初始化。在每次搜索關(guān)鍵詞時(shí),都會(huì)先使用BloomFilter判斷關(guān)鍵詞是否在Lucene索引庫(kù)中。
這里設(shè)定布隆過(guò)濾器的誤判率p為0.01%,商品信息個(gè)數(shù)n為1100000,經(jīng)過(guò)計(jì)算得出哈希函數(shù)個(gè)數(shù)k為14,布隆過(guò)濾器bitarray大小m為2574.11KB。
中文分詞是中文文本處理的一個(gè)基礎(chǔ)步驟,也是全文搜索技術(shù)的核心關(guān)鍵之一,分詞效果的好壞以及效率直接關(guān)系到搜索引擎的綜合表現(xiàn)。目前,常見(jiàn)的中文分詞器[10]大致可歸納為:詞典分詞方法、理解分詞方法、統(tǒng)計(jì)分詞方法、組合分詞方法。其中,組合分詞方法[11]是利用各個(gè)方法的優(yōu)點(diǎn),彌補(bǔ)方法的不足,組合部分方法以更好地解決分詞問(wèn)題。
Lucene自帶的中文分詞器,包括StandardAnalyzer和CJKAnalyzer。前者是單字分詞,就是按照中文一個(gè)字一個(gè)字地進(jìn)行分詞;后者是二分法分詞,即按兩個(gè)字進(jìn)行切分。上邊兩個(gè)分詞器無(wú)法滿(mǎn)足對(duì)中文的需求。
HanLP中文分詞器具備功能完善、性能高效、架構(gòu)清晰、語(yǔ)料時(shí)新、可自定義的特點(diǎn)。默認(rèn)模型訓(xùn)練自全世界最大規(guī)模的中文語(yǔ)料庫(kù),同時(shí)自帶一些語(yǔ)料處理工具,幫助用戶(hù)訓(xùn)練自己的模型。目前支持包括Solr(7.x)在內(nèi)的任何基于Lucene(7.x)的系統(tǒng)。
商品排序其實(shí)就是計(jì)算搜索關(guān)鍵詞和所有物品的相關(guān)程度,關(guān)聯(lián)程度計(jì)算就是排序,Lucene會(huì)對(duì)分詞列的精確查詢(xún)條件進(jìn)行打分。打分排序[7-8]是搜索引擎重要一部分,能夠評(píng)判查詢(xún)條件和文檔的匹配度,提高檢索質(zhì)量。打分過(guò)程會(huì)消耗額外I/O、需要更多CPU計(jì)算、加載整個(gè)倒排表,拖累了查詢(xún)速度,特別是在文檔數(shù)非常多的情況下。而在商品搜索的需求中,用戶(hù)只關(guān)心那些和搜索關(guān)鍵詞高度相關(guān)的商品信息,對(duì)于相似度低的商品并不需要顯示出來(lái),所以系統(tǒng)過(guò)濾掉低相似度的商品,減少參與排序的商品數(shù)量,降低時(shí)間復(fù)雜度。在系統(tǒng)查詢(xún)開(kāi)始階段,設(shè)定相似度最低閾值score。
目前對(duì)于相似度最低閾值的設(shè)定沒(méi)有可供參考的資料,而且相似度值會(huì)根據(jù)不同的關(guān)鍵詞、關(guān)鍵詞數(shù)量、文檔長(zhǎng)度、文檔內(nèi)容等因素得到0-1之間的任意數(shù)值,所以最低閾值score設(shè)定為固定值顯然不合適,必須是一個(gè)動(dòng)態(tài)的值。參考Lucene在計(jì)算相關(guān)度得分的算法BM25[12],算法公式如下,可以針對(duì)不同查詢(xún)關(guān)鍵詞利用該公式計(jì)算出得分的最大值和最小值,取20%作為相似度最低閾值score。
其中N為索引中的全部文檔數(shù),n(qi)為包含了qi的文檔數(shù),這兩個(gè)值都是可以從索引庫(kù)讀取的;k1、b為調(diào)節(jié)因子,通常根據(jù)經(jīng)驗(yàn)設(shè)置,一般k1=2,b=0.75;fi為qi在d中的出現(xiàn)頻率,也就是關(guān)鍵詞在商品名稱(chēng)中出現(xiàn)的次數(shù),取值一般是0-3;dl為文檔d的長(zhǎng)度,avgdl為所有文檔的平均長(zhǎng)度,這兩者商的取值區(qū)間如下公式所示,取值一般是在0.6-1.5。
其中m表示文檔d長(zhǎng)度的最大值,n表示文檔d長(zhǎng)度的最小值,根據(jù)分析,m大約是n的2倍左右。
數(shù)據(jù)庫(kù)中的商品表products結(jié)構(gòu)如表1所示,其中選取字段pid、name、catalog_name、price、description和picture映射為索引庫(kù)字段id、prod_pname、prod_catalog_name、prod_price、prod_description和prod_picture,根據(jù)這6個(gè)字段將數(shù)據(jù)從數(shù)據(jù)庫(kù)導(dǎo)入到索引庫(kù)中。
表1 products表結(jié)構(gòu)
為了實(shí)現(xiàn)通過(guò)索引庫(kù)加快商品搜索效率的需求,將關(guān)系數(shù)據(jù)庫(kù)中的數(shù)據(jù)導(dǎo)入到Solr,從而構(gòu)建起商品數(shù)據(jù)索引庫(kù),由查詢(xún)數(shù)據(jù)庫(kù)轉(zhuǎn)變?yōu)闄z索索引庫(kù)。構(gòu)建索引庫(kù)過(guò)程中,考慮到數(shù)據(jù)庫(kù)搜索的結(jié)果就是“表”中若干“元組”的集合,可以把“元組”的集合看作是倒排表中的文件鏈表,這樣通過(guò)關(guān)鍵詞找出對(duì)應(yīng)的文件集合,也就是過(guò)濾出符合關(guān)鍵詞條件的“元組”集合。
使用Solr服務(wù)器的dataimport工具將MySQL數(shù)據(jù)庫(kù)中的商品表products導(dǎo)入到索引庫(kù)。一般來(lái)說(shuō),商品搜索關(guān)鍵詞只出現(xiàn)在商品的名稱(chēng)信息當(dāng)中,所以對(duì)“商品名稱(chēng)”字段進(jìn)行索引。
商品搜索系統(tǒng)是基于Tomcat服務(wù)器、SpringMVC框架、MySQL數(shù)據(jù)庫(kù)和Solr搜索引擎等。設(shè)計(jì)結(jié)構(gòu)主要由數(shù)據(jù)層、業(yè)務(wù)層和客戶(hù)層組成,數(shù)據(jù)層包括存儲(chǔ)原始數(shù)據(jù)的MySQL數(shù)據(jù)庫(kù)和存儲(chǔ)索引文件的Lucene索引庫(kù);業(yè)務(wù)層主要是由Solr Core實(shí)現(xiàn)的索引和搜索兩個(gè)功能,預(yù)先構(gòu)建、更新索引庫(kù),搜索時(shí)先將查詢(xún)關(guān)鍵詞經(jīng)過(guò)布隆過(guò)濾器的預(yù)判,然后查詢(xún)索引庫(kù),獲取商品信息;客戶(hù)層也就是系統(tǒng)界面,接受用戶(hù)的查詢(xún)請(qǐng)求,并將查詢(xún)結(jié)果展現(xiàn)在頁(yè)面當(dāng)中。整個(gè)系統(tǒng)的運(yùn)行流程都由SpringMVC進(jìn)行控制管理,構(gòu)建索引庫(kù)以及分析搜索語(yǔ)句都需要HanLP中文分詞器的參與。
用戶(hù)除了能夠通過(guò)搜索框查詢(xún)商品之外,還可以點(diǎn)擊分類(lèi)瀏覽特定類(lèi)型商品,選擇一定價(jià)格區(qū)間的商品,對(duì)商品價(jià)格排序等。
為了分析比較基于Solr搜索服務(wù)器的本系統(tǒng)和基于MySQL數(shù)據(jù)庫(kù)的傳統(tǒng)SQL模糊查詢(xún)的性能差異,預(yù)先準(zhǔn)備了11萬(wàn)條商品記錄的測(cè)試數(shù)據(jù)集,還有用于搜索的7個(gè)存在的商品詞和1個(gè)不存在的商品詞,針對(duì)這8個(gè)商品詞分別使用本系統(tǒng)進(jìn)行直接搜索和使用SQL語(yǔ)句“select*from products where pname like'%關(guān)鍵詞%';”進(jìn)行模糊查詢(xún),對(duì)比兩者的檢索時(shí)間和檢索數(shù)量,實(shí)驗(yàn)硬件環(huán)境Intel Core i5 2.3GHz、8GB內(nèi)存,得出如表2所示的實(shí)驗(yàn)數(shù)據(jù)。
表2 基于Solr檢索和數(shù)據(jù)庫(kù)模糊檢索的結(jié)果對(duì)比
對(duì)比基于Solr搜索和基于MySQL數(shù)據(jù)庫(kù)模糊查詢(xún)的實(shí)驗(yàn)結(jié)果,發(fā)現(xiàn)兩者在檢索時(shí)間方面差別較大,結(jié)果數(shù)量上差別較小?;赟olr搜索的時(shí)間基本在100毫秒以?xún)?nèi),完全能滿(mǎn)足用戶(hù)對(duì)實(shí)時(shí)性的要求,而基于MySQL數(shù)據(jù)庫(kù)模糊查詢(xún)的時(shí)間大約在20000毫秒上下,兩者在檢索時(shí)間上相差200多倍,所以通過(guò)利用Lucene全文檢索索引庫(kù)技術(shù),商品搜索效率得到了極大提高。觀察實(shí)驗(yàn)結(jié)果,發(fā)現(xiàn)搜索關(guān)鍵詞“襪子”、“眼鏡”和“牙膏”,雖然兩種方式的搜索結(jié)果數(shù)量一致,但是Solr檢索速度快很多。通過(guò)對(duì)比各關(guān)鍵詞的Solr檢索時(shí)間,當(dāng)檢索詞是最小分詞時(shí),其搜索時(shí)間會(huì)比較短;當(dāng)檢索詞包含多個(gè)最小分詞,如“智能手機(jī)”、“碗綠色”,其搜索時(shí)間相對(duì)會(huì)長(zhǎng)些。而對(duì)比各關(guān)鍵詞的模糊查詢(xún)時(shí)間,其檢索時(shí)間與檢索詞長(zhǎng)短關(guān)系并不大,這其實(shí)是由于模糊查詢(xún)是對(duì)數(shù)據(jù)庫(kù)所有商品信息記錄進(jìn)行逐字匹配,所以耗時(shí)基本相差不大。最后,對(duì)于不存在的商品進(jìn)行檢索,兩者的結(jié)果數(shù)量都為0,但是本系統(tǒng)采用了布隆過(guò)濾器,預(yù)先判斷商品不存在,避免查詢(xún)索引庫(kù),減少了檢索時(shí)間??偟膩?lái)說(shuō),基于Solr搜索服務(wù)器的檢索性能比基于數(shù)據(jù)庫(kù)的檢索性能要高出很多。
通過(guò)對(duì)Solr搜索引擎和底層的Lucene檢索庫(kù)的研究,并根據(jù)商品搜索的實(shí)際需求分別對(duì)排序、關(guān)鍵詞過(guò)濾實(shí)現(xiàn)了優(yōu)化,構(gòu)建出較為完整的商品搜索系統(tǒng)。經(jīng)過(guò)實(shí)驗(yàn)的對(duì)比分析,得出系統(tǒng)實(shí)現(xiàn)了正常運(yùn)行,更為重要的是性能較傳統(tǒng)數(shù)據(jù)庫(kù)的查詢(xún)性能提升非常明顯,說(shuō)明系統(tǒng)的設(shè)計(jì)達(dá)到了最初的目的。