目錄javascript
Lucene.net站內搜索—一、SEO優化
Lucene.net站內搜索—二、Lucene.Net簡介和分詞
Lucene.net站內搜索—三、最簡單搜索引擎代碼
Lucene.net站內搜索—四、搜索引擎初版技術儲備(簡單介紹Log4Net、生產者消費者模式)
Lucene.net站內搜索—五、搜索引擎初版實現
Lucene.net站內搜索—六、站內搜索第二版css
咱們先假設用一張表來存儲用戶全部的關鍵字搜索和次數,以下:html
關鍵字名稱java |
搜索次數jquery |
新四大名捕面試 |
3ajax |
新圓月彎刀數據庫 |
4json |
北京愛情故事數組 |
6 |
這樣實現的缺點:一、沒法實現搜索「最近7天的熱詞」二、性能差,由於update qCount=qCount+1 where Keyword=「新四大名捕」須要鎖定行。
搜索記錄表用Guid。自動增加(標識列)是須要依賴於「上一次的值」,因此須要排隊,性能差;而Guid的生成則是獨立的,不須要依賴,因此性能好。
select top 10 Keyword,count(*) from T_SearchRecords where Keyword like '新四大名捕%' group by Keyword order by Count(*) desc
一、Like不必定會全表掃描。「%a%」會,而"a%"則不會。
二、group by確定很是消耗資源。
由於對於每次搜索都要:group by、order by、where like。全部的搜索的group by、order by都是同樣的,不必重複,因此應該吧「group by、order by」結果緩存起來。
所以進行數據的彙總結果插入:T_SearchRecordsSum(Keywords,SearchCount)表。天天彙總一次,這樣會有數據不及時的狀況,可是並非實時性很是強的,所以不要緊,大不了提升彙總的頻率。
Keywords SearchCount
新四大名捕 5
新圓月彎刀 3
delete from T_SearchRecordsSum; insert into T_SearchRecordsSum(Keywords,SearchCount) select Keyword,count(*) from T_SearchRecords group by Keyword order by Count(*) desc;
兩張表,一張明細、一張彙總,定時把明細表的數據插入彙總表,查詢的時候到彙總表查詢。
因爲明細表的主鍵不須要連續,並且用自動增加字段會排隊、加鎖從而下降效率,所以主鍵用Guid。(爲啥文章用自動增加?url短、好看。)
insert into T_KeyWordsRank(Id,KeyWords,SearchTimes) select newid(), KeyWords,Count(*) from T_SearchDetails where DateDiff(day,SearchDateTime,GetDate())<=7 group by KeyWords
Group by效率低,寫SQLServer的是牛人,但不是神人
Quartz.Net是一個定時任務框架,能夠實現異常靈活的定時任務,開發人員只要編寫少許的代碼就能夠實現「每隔1小時執行」、「天天22點執行」、「每個月18日的下午執行8次」等各類定時任務。
Quartz.Net中的概念:計劃者(IScheduler)、工做(IJob)、觸發器(Trigger)。給計劃者一個工做,讓他在Trigger(什麼條件下作這件事)觸發的條件下執行這個工做
將要定時執行的任務的代碼寫到實現IJob接口的Execute方法中便可,時間到來的時候Execute方法會被調用。
CrondTrigger是經過Crond表達式設置的觸發器,還有 SimpleTrigger等簡單的觸發器。能夠經過TriggerUtils的MakeDailyTrigger、MakeHourlyTrigger等方法簡化調用。調用代碼參考備註。
實現:用Quartz.Net完成定時搜索數據彙總。
第一個用戶訪問咱們的WebApplication的時候,Application_Start才運行。
//0 15 10 ? * *" :Fire at 10:15am every day CronTrigger trigger = new CronTrigger("trigger1", "group1", "job1", "group1"); trigger.CronExpressionString = 「0 15 10 ? * *」; //每隔一段時間執行任務 IScheduler sched; ISchedulerFactory sf = new StdSchedulerFactory(); sched = sf.GetScheduler(); JobDetail job = new JobDetail("job1", "group1", typeof(IndexJob));//IndexJob爲實現了IJob接口的類 DateTime ts = TriggerUtils.GetNextGivenSecondDate(null, 5);//5秒後開始第一次運行 TimeSpan interval = TimeSpan.FromHours(1);//每隔1小時執行一次 Trigger trigger = new SimpleTrigger("trigger1", "group1", "job1", "group1", ts, null, SimpleTrigger.RepeatIndefinitely, interval);//每若干小時運行一次,小時間隔由appsettings中的IndexIntervalHour參數指定 sched.AddJob(job, true); sched.ScheduleJob(trigger); sched.Start();
要關閉任務定時則須要sched.Shutdown(true)
搜索建議、最新熱門搜索都是基於已有的用戶搜索記錄。SEO的歪門邪道:刷百度搜相關詞彙(SEO最終目的仍是讓用戶找到咱們的網站)。按期清除舊的歷史數據,防止數據庫太大
每次有用戶搜索都把用戶的搜索行爲記錄下來,供熱門搜索和搜索建議用。三個字段:搜索時間、搜索詞(一句話)、訪問者IP地址。由於自動增加字段(標識列)有加鎖的機制,因此慢,這裏呢的Id也不會在邏輯中有,因此用Guid(不會加鎖)
使用三層,增長插入記錄的方法,在搜索的時候插入記錄,IP地址:Request.UserHostAddress。
todo:爲了不groupby耗時,每小時作一次group by
關於自動搜索功能這裏我使用jquery ui 來實現,先下載AutoComplete.rar下載路徑:http://files.cnblogs.com/files/jiekzou/AutoComplete.rar
固然,你也能夠在google搜索「JQuery AutoComplete」,找到了JQueryUI庫中的AutoComplete組件。http://jqueryui.com/demos/autocomplete/
效果圖以下:
新建AutoComplete.aspx
要求服務器返回搜索建議詞彙的時候將詞彙以字符串數組的形式(JSon格式)返回給瀏覽器。
不要忘了引入jquery、jqueryui的js和css,注意順序。
autocomplete的source屬性指定自動完成數據的數據來源
生命週期的問題:在用戶敲入文字的時候,Autocomplete組件向ashx頁面發出ajax請求,而且將ashx返回的json格式的數組顯示出來。(*)defer請求
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AutoComplete.aspx.cs" Inherits="BookShop.Web.AutoComplete" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <link href="/Css/themes/ui-lightness/jquery-ui-1.8.2.custom.css" rel="stylesheet" type="text/css" /> <script src="/js/jquery-1.4.2.js" type="text/javascript"></script> <script src="/js/jquery-ui-1.8.2.custom.min.js" type="text/javascript"></script> <script type="text/javascript"> $(function () { $("#<%=txtSearch.ClientID%>").focus(function () { if ($(this).val() == "請輸入搜索內容") { $(this).css("color", "black").val(""); } }).blur(function () { //光標離開 if ($(this).val() == "") { $(this).css("color", "Gray").val("請輸入搜索內容"); } }); $("#<%=txtSearch.ClientID%>").autocomplete({ source: "/ashx/AutoComplete.ashx", minLength: 1 }); }); </script> </head> <body> <form id="form1" runat="server"> <div> <asp:TextBox ID="txtSearch" runat="server" Width="432px" style="color:grey">請輸入搜索內容</asp:TextBox> <asp:Button ID="btnSearch" runat="server" Text="Search" /> </div> </form> </body> </html>
新建通常處理程序:AutoComplete.ashx
public class AutoComplete : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; string term = context.Request.QueryString["term"]; //BLL.BookManager bll = new BookShop.BLL.BookManager(); List<Book> bookList = new List<Book>();//bll.GetBooks(term); bookList.Add(new Book {Id=1,ISBN="01",PublishDate=DateTime.Now,Title="bad",UnitPrice=10.00m }); bookList.Add(new Book { Id = 2, ISBN = "02", PublishDate = DateTime.Now, Title = "Anple", UnitPrice = 10.00m }); bookList.Add(new Book { Id = 3, ISBN = "03", PublishDate = DateTime.Now, Title = "Acccd", UnitPrice = 10.00m }); bookList.Add(new Book { Id = 4, ISBN = "04", PublishDate = DateTime.Now, Title = "bcccd", UnitPrice = 10.00m }); List<string> list = new List<string>(); for (int i = 0; i < bookList.Count; i++) { if (bookList[i].Title.ToLower().LastIndexOf(term.ToLower())==0) { list.Add(bookList[i].Title); } } //序列化對象 System.Web.Script.Serialization.JavaScriptSerializer js = new System.Web.Script.Serialization.JavaScriptSerializer(); context.Response.Write (js.Serialize(list.ToArray())); } public bool IsReusable { get { return false; } } }
在搜索框下方顯示搜索次數最多的語句,語句添加超連接,用戶能夠點擊語句的超連接快捷的開始搜索。用ObjectDataSource和Repeater控件。
在搜索框下方顯示熱門詞彙有利於SEO,方便著名的搜索引擎收錄網站的搜索結果頁面,由於搜索引擎只認超連接。不少站內搜索都有熱門詞彙就是這麼回事。
熱門詞彙是全部訪問者每次訪問頁面的時候都要顯示的,因此須要緩存。這個是緩存的一個很好的例子,面試的時候問到緩存的問題舉這個例子就很好。
顯示數據庫中全部搜索次數最多的語句,好嗎?很差,容易造成馬太效應。只取一週以內的最熱門。
在常常須要進行檢索的字段上添加索引,能夠提升檢索速度。
<div class="rp_5equalcol"><asp:HyperLink Text='<%# Eval("KeyWord")%>' NavigateUrl='<%#EvalSearchURL(Eval("KeyWord").ToString()) %>' runat="server"></asp:HyperLink></div>
private string GetPageAbsolutePath() { string pageurl = this.AppRelativeVirtualPath; return this.ResolveUrl(pageurl); } public string EvalSearchURL(string kw) { string pageurl = GetPageAbsolutePath(); return string.Format("{0}?kw={1}", pageurl,HttpUtility.UrlEncode(kw)); }
開發站內搜索的分頁功能。
可以SEO的無刷新分頁。
這裏你可使用現有的第三方分頁控件,也能夠本身寫一個或本身改造一個,注意使用ajax無刷新分頁。
這裏我只作簡單介紹,有興趣的朋友能夠本身去研究下。
(*) IndexSearcher是Searcher類的一個子類,Searcher類還有其餘子類,MultiSearcher(在多個索引上搜索),ParallelMultiSearcher(在多個索引上並行搜索,速度更快),作更大的搜索引擎會用到。