Lucene是一個開源的搜索引擎,開發語言是Java,Lucene.net是它的.NET版本。可以在C#中方便的調用。
Lucene.net目前最新版本是3.0.3,你可以從官方網站下載到最新版本:http://lucenenet.apache.org/
使用Lucene.net進行全文查找首先要根據數據創建索引,然后再根據索引來查找關鍵字。本文不做任何原理性的解釋,需要深入研究的請自行Google之。
創建索引
還是直接上代碼的比較好:
IndexWriter writer = new IndexWriter(FSDirectory.Open(new DirectoryInfo(indexDirectory)), analyzer, true, IndexWriter.MaxFieldLength.LIMITED); for (int i = 0; i < files.Count(); i++) { FileInfo fileInfo = files[i]; StreamReader reader = new StreamReader(fileInfo.FullName); OutputMessage("正在索引文件[" + fileInfo.Name + "]"); Document doc = new Document(); doc.Add(new Field("FileName", fileInfo.Name, Field.Store.YES, Field.Index.ANALYZED)); doc.Add(new Field("Author", reader.ReadLine(), Field.Store.YES, Field.Index.ANALYZED)); doc.Add(new Field("Content", reader.ReadToEnd(), Field.Store.NO, Field.Index.ANALYZED)); doc.Add(new Field("Path", fileInfo.FullName, Field.Store.YES, Field.Index.NO)); writer.AddDocument(doc); writer.Optimize(); } writer.Dispose();
在上面的代碼中,我們對文本文件進行了索引,每一個文件都保存了FileName(文件名)、Author(作者)、Content(內容)、Path(文件路徑)幾個字段。跟數據庫中的字段很相似。
使用中文分詞
目前中文分詞有Lucene.Net.Analysis.Cn.ChineseAnalyzer 和盤古分詞,我們在測試中使用前者,更方便我們做測試。
Lucene.Net.Analysis.Cn.ChineseAnalyzer包含在源代碼中,你可以把它復制到你的源代碼中,也可以編譯以后引用。我這里為了方便,直接復制到源代碼中的。建議在實際使用的時候,編譯然后添加引用。
全文查找
還是上代碼吧,看上去更直接。
IndexReader reader = null; IndexSearcher searcher = null; try { reader = IndexReader.Open(FSDirectory.Open(new DirectoryInfo(indexDirectory)), true); searcher = new IndexSearcher(reader); //創建查詢 PerFieldAnalyzerWrapper wrapper = new PerFieldAnalyzerWrapper(analyzer); wrapper.AddAnalyzer("FileName", analyzer); wrapper.AddAnalyzer("Author", analyzer); wrapper.AddAnalyzer("Content", analyzer); string[] fields = {"FileName", "Author", "Content"}; QueryParser parser = new MultiFieldQueryParser(Lucene.Net.Util.Version.LUCENE_30, fields, wrapper); Query query = parser.Parse(keyword); TopScoreDocCollector collector = TopScoreDocCollector.Create(num, true); searcher.Search(query, collector); var hits = collector.TopDocs().ScoreDocs; int numTotalHits = collector.TotalHits; OutputMessage("查找 " + keyword + " ...共找到 " + numTotalHits + "個匹配的文檔"); //以后就可以對獲取到的collector數據進行操作 for (int i = 0; i < hits.Count(); i++) { var hit = hits[i]; Document doc = searcher.Doc(hit.Doc); Field fileNameField = doc.GetField("FileName"); Field authorField = doc.GetField("Author"); Field pathField = doc.GetField("Path"); OutputMessage(fileNameField.StringValue + "[" + authorField.StringValue + "],匹配指數:" + Math.Round(hit.Score * 100, 2) + "%"); OutputMessage(pathField.StringValue); OutputMessage(string.Empty); } } finally { if (searcher != null) searcher.Dispose(); if (reader != null) reader.Dispose(); }
上面的這段代碼可以是實現多關鍵字的查找。需要說明的是,貌似在得到檢索到的文檔的地方,跟之前的版本有一些不同(我拷貝別人的代碼沒辦法直接運行)……
另外,此處檢索的行數受到num的影響,但返回的總行數是不受影響的,如果需要得到總行數,可以在第一次檢索以后得到總行數,然后將總行數賦值給num,在進行新一次的檢索。
按照慣例,附上源代碼