像www.verycd.com、部落格園、淘寶、京東都有實作站内搜尋功能,站内搜尋無論在性能和使用者體驗上都非常不錯,本節,通過使用Lucene.Net來實作站内搜尋。
示範效果預覽如下圖10-22~10-24所示。

圖10-22
圖10-23
圖10-24
在10.4節,已經完成了搜尋的第一個版本,但是還有許多地方需要優化。比如說,我要統計關鍵詞搜尋的頻率高的詞,也即熱詞,以及像百度搜尋那樣,在輸入關鍵字後,會自動把搜尋相關的熱詞自動以下拉清單的形式帶出來。還有諸如搜尋結果分頁,檢視文章明細等。
思路:
1、 首先,我們腦海裡要明确一點:搜尋關鍵字的統計,實時性是不高的。也就是說我們可以定期的去進行統計。
2、 客戶的每一次搜尋記錄,我們都需要存起來,這樣才能夠統計得到。
從第1點,我們腦海中就會呈現一張彙總統計表,從第2點中,我們會想到使用一張搜尋記錄明細表。那方案就很明了了,隻需要定期的從明細表中Group by查詢,然後把查詢結構放到彙總表中。怎麼放到彙總表中?是直接Update更新嗎?其實我們可以有更快捷的方式,那就是對彙總表先進行truncate,然後再進行insert操作。
表10-1 搜尋彙總統計表SearchTotals
字段名稱
字段類型
說明
Id
char(36)
主鍵,采用Guid方式存儲
KeyWords
nvarchar(50)
搜尋關鍵字
SearchCounts
int
搜尋次數
表10-2 搜尋明細表SearchDetails
SearchDateTime
datetime
搜尋時間
操作步驟:
(1)在Models檔案夾中,建立兩個類SearchTotal、SearchDetail。
SearchTotal.cs代碼:
SearchDetail.cs代碼:
(2)修改SearchDemoContext類,新增了屬性SearchTotal、SearchDetail。
3)更新資料庫
由于修改了EF上下文,新增了兩個模型類,是以需要進行遷移更新資料庫操作。
将應用程式重新編譯,然後選擇工具->庫程式包管理器->程式包管理控制台。
打開控制台,輸入enable-migrations -force ,然後回車。回車後會在項目項目資料總管中會出現Migrations檔案夾,打開Configuration.cs 檔案,将AutomaticMigrationsEnabled 值改為 true,然後在控制台中輸入 update-database 運作。操作完成之後,會在資料庫SearchDemo中多建立兩張表SearchTotals、SearchDetails,而原來的Articles表保持不變。如圖10-20所示。
圖10-20
(4)儲存搜尋記錄
使用者在每次搜尋的時候,要把搜尋記錄存入SearchDetails表中。為了友善,這裡我是在使用者每次點選搜尋之後就立即往SearchDetails表中插入記錄了,也就是同步操作,而實際上,如果為了提升搜尋的效率,我們可以采用異步操作,即把搜尋記錄的資料先寫入redis隊列中,背景再開辟一個線程來監聽redis隊列,然後把隊列中的搜尋記錄資料寫入到資料表中。因為在每次點選搜尋的時候,我們把記錄往redis寫和把記錄直接往關系型資料庫中寫的效率是相差很大的。
(5)定時更新SearchTotals表記錄
看到這種定時任務操作,這裡可以采用Quartz.Net架構,為了友善,我把Quartz.Net的Job寄宿在控制台程式中,而實際工作中,我則更傾向于将其寄宿在Windows服務中。如果有必要,可以把這個定時更新SearchTotals表記錄的程式部署到獨立的伺服器,這樣可以減輕Web伺服器的壓力。
建立控制台程式QuartzNet,添加Quartz.dll和Common.Logging.dll的程式集引用,這裡采用Database First的方式,添加ADO.NET實體資料模型,把表SearchTotals、SearchDetails添加進來。
2.添加KeyWordsTotalService.cs類,裡面封裝兩個方法,清空SearchTotals表,然後把SearchDetails表的分組查詢結構插入到SearchTotals表,這裡我隻統計近30天内的搜尋明細。
3. 添加TotalJob.cs類,繼承Ijob接口,并實作Execute方法。
4.修改Program.cs類
這裡我是直接把Job和計劃都直接寫到代碼中了,理由還是因為友善。而實際工作中,我們應當把這些資訊盡量寫到配置檔案中,這樣後面改動起來友善,不需要修改代碼,隻需要修改配置檔案。
為了盡快看到效果,我這裡是每隔50秒就進行了一次統計操作,而在實際應用中,我們的時間間隔可能是幾個小時甚至一天,因為像這樣的大資料統計,對實時性的要求不高,我們可以盡量減少對資料庫的IO讀寫次數。
保持運作控制台程式QuartzNet,然後我們去進行搜尋操作,這樣背景就定期的生成了搜尋統計記錄。
其實就是從表SearchTotals中按照搜尋次數進行降序排列,然後取出數條記錄而已。
LastSearch控制器中的Index方法中添加如下代碼:
View視圖中
接下來,我想要實作如下圖10-21所示的效果:
圖10-21
當我點選一個熱詞的時候,自動加載到文本框,并點選“搜尋”按鈕。
在View中添加代碼:
這裡我引入一個第三方js架構Autocomplete,它能在文本框中輸入文字的時候,自動從背景抓去資料下拉清單。
雲盤中我提供了Autocomplete.rar,将其解壓,然後拷貝到SearchDemo項目中的lib目錄下。
在SearchDemo項目中的KeyWordsTotalService.cs類中添加方法
然後在LastSearch控制器中添加方法:
我們來看View:
在10.4中,隻支援在内容中對關鍵詞進行搜尋,而實際上,我們可能既要支援在标題中搜尋,也要在内容中搜尋。
這裡引入了BooleanQuery,我們的查詢條件也添加了一個titleQuery。
搜尋方法中,如下代碼有修改:
前面我們在搜尋的時候,其實采用的都是與查詢,也就是說,我輸入“諸葛亮周瑜”,則隻會查找出,既存在諸葛亮,又存在周瑜的記錄。那麼有時候,我們是想查詢存在諸葛亮或者周瑜的記錄的,這也就是所謂的或查詢。
我在界面添加一個複選框“或查詢”,來讓使用者決定采用何種方式進行查詢。
至于分頁,這裡采用MvcPager,關于MvcPager的使用方法請參見4.6.3。
View完整代碼預覽:
View Code
然後,各位看官請再看LastSearch控制器中的方法:
至此,站内搜尋的基本功能均已完成。
本文轉自鄒瓊俊部落格園部落格,原文連結:http://www.cnblogs.com/jiekzou/p/5661752.html,如需轉載請自行聯系原作者