打開百度輸入
該項目最終在在我項目的搜索結果
站內搜索也要實現類似功能。最基礎的做法,寫個方法查數據庫搜索歷史綜合表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也可以。只要你願意用數據庫搞的話。
不過誰還知道,有沒有什么更好的辦法解決這個問題?
記錄到這里。渣渣代碼不上傳了,如果有誰剛好需要寫這樣的功能,又實在寫不出來代碼的內線我,我發一份給你。。。。。