利用 lucene.net 實現高效率的 WildcardQuery ,記一次類似百度搜索下拉關鍵字聯想功能的實現。


打開百度輸入 

該項目最終在在我項目的搜索結果

 

站內搜索也要實現類似功能。最基礎的做法,寫個方法查數據庫搜索歷史綜合表keywordSearch(先將被搜索過的關鍵字記錄到一張表,記錄好他們被搜索的次數、上次搜索的有多少結果)

大概一條sql語句:select keyword,searchCount,xxxx from table where keyword like '會計%'

當表 keywordSearch 記錄很有幾百上千萬的時候,like顯然不能及時響應了。但是這種關鍵字聯想的一旦有延遲返回,那是很不好的體驗。還沒等你返回一次聯想結果,用戶早就自己輸完了。。。。。那還聯想個球。

 

然后這個時候,想到的是用lucene.net

二話不說開干。很快實現了demo,創建了索引2g,搜索核心代碼如下:(渣渣代碼,勿噴)

測試之,大概在1秒內能返回結果,但是還是不夠快,有明顯的延遲感。

尼瑪。。。。。想不到好辦法解決,然后試了試用RAMDirectory ,還是不行,畢竟 RAMDirectory 只是將索引一次性讀到內存,避免了一個預熱的過程,所以瓶頸感覺應該出在了這個WildcardQuery上(誰知道lucene.net要實現這種查詢,還有其他辦法效率高嗎?看到的有知道的請評論告訴我謝謝。)。

 當時想的是,看樣子只能丟掉一些關鍵字,比如只匯總最近一年的關鍵字,把索引搞小一些。

but,周末休息了一下,讓我想到了一個辦法。

既然要減少單個索引體積,那我為什么不拆分索引?

首先,創建索引的時候,根據關鍵字的第一個漢字的首字母,來決定放在哪個索引。比如 “會計學” 放在 D:\LuceneIndex\Searchkeyword\k\ 目錄下的索引,"管理學"放在 D:\LuceneIndex\Searchkeyword\g\ 目錄。

然后檢索的時候我也根據用戶輸入的關鍵字,檢索不同的目錄。這樣應該就能解決這個問題。

說干就干,又開始改代碼。

因為代碼篇幅比較大,我就貼一點核心部分。(再次請求原諒我的渣渣代碼。。。。)

那個 GetIndexWriter 方法,就是根據漢字首拼字母來獲取的,

BLLIndexWriter類里面 用  Dictionary<string, string> 對象,來裝所有字母和它對應的索引路徑。

然后用了一個 Dictionary<string, IndexWriter> 對象,來裝所有字母,和它所對應的 IndexWriter 對象。

當索引全部創建完畢以后,遍歷了裝所有 IndexWriter 的對象,然后一個個關閉並優化。

最后,索引就一一對應到不同目錄了

見圖,原來的索引和現在的索引。

平均分了這么多以后,搜索基本上是馬上就出結果了。因為每一個都只有幾十MB一百MB的。這點量,lucene的通配還是能搞的定的。

對於此類查詢,數據庫上分表,然后like也可以。只要你願意用數據庫搞的話。

不過誰還知道,有沒有什么更好的辦法解決這個問題?

記錄到這里。渣渣代碼不上傳了,如果有誰剛好需要寫這樣的功能,又實在寫不出來代碼的內線我,我發一份給你。。。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM