為什么要封裝
真不知道用什么標題合適,我這幾天在研究Lucene.Net,覺得把Lucene.Net封裝為一個獨立的服務器,再提供一個給客戶端調用的Api組件應該是一件很意思的事,主要優勢有以下:
1、可以將索引和檢索的壓力放到網絡的其它主機上,服務器不用再開發,直接運行就可以;
2、客戶端完全可以脫離Lucene.Net,只要關心相關的幾個Api就可以;
3、多個客戶端也可以共用同一個索引,也可以不共用。
如上圖,所有的客戶端都只依賴於提供的Api組件,就可以操作Lucene服務器了。
APi組件
對於客戶端而已,只需要關注APi組件,這個APi組件命名為LuceneLib,提供設置索引、刪除索引、查詢索引方法:
緊密結合C#語言的APi風格
因為客戶端與Api是直接接觸的,所以如何將APi設計為簡單易用將面臨下面的挑戰:
1、APi在設置索引或查詢索引時,Model為強類型;
2、查詢索引時,有很多相關參數,比如關鍵字、查詢的字段、排序字段、是否關鍵字高亮、如何高亮、分頁功能。
LuceneLib給出緊密結合C#語言的APi風格,並完美地解決了上面兩個難題:
使用泛型,強類型模型自動轉換為通訊傳輸層的模型,反過來也是,所以服務器可以不用知道客戶端的MODEL的類型。
/// <summary> /// Model為News索引名為Index_News /// </summary> private Lucene<News> client = new Lucene<News>("Index_News"); /// <summary> /// 設置索引 /// </summary> /// <param name="title">標題</param> /// <param name="content">內容</param> /// <returns></returns> private async Task<bool> SetIndex_Test(string title, string content) { var news = new News { Id = Guid.NewGuid(), OrderIndex = Environment.TickCount, CreateTime = DateTime.Now, Title = title, Content = content }; return await client.SetIndex(news); }
LINQ風格的索引查詢Api,各項調用不按順序或省略相關項都不影響結果,MatchField方法提供N種重載,可以實現個性化的搜索結果。
/// <summary> /// 索引查詢 /// </summary> /// <param name="keywords"></param> /// <returns></returns> private async Task<List<News>> SearchIndex_Test(string keywords) { return await client .SearchIndex(keywords) .MatchField(item => item.Title, "high-light") .MatchField(item => item.Content, Color.Red, 100) .OrderByDescending(item => item.OrderIndex) .Skip(0) .Take(10) .ToList(); }
相關技術
1、訊功能依賴於NetworkSocket項目,https://github.com/xljiulang/NetworkSocket,所有Api都是異步的,可以與async和await使用;
2、業務模型和通訊模型轉換過程做了反射優化。
在相關項目工程在哪里
項目放在了github,https://github.com/xljiulang/LuceneServer
有什么建議可以在這里或github上提。