Lucene 使用
這幾天無聊,看了一下Lucene。使用如下:
1.下載Lucene,可以下載下來Lucene.net源碼。
2.建立一個Templucene工程中,並且在工程中添加lucene工程,或則是lucene引用。我的介面是這樣的。
3.建立目錄在debug下建立IndexDirectory,並且在這裡文件下建立2個文件夾,一個放要查詢的文檔temp,一個放生成的索引文件index。
4.建立處理類LuceneFunction,代碼如下:
public class LuceneFunction
{
private const string FILE_KEY_NAME = "filename";//文件名
private const string CONTENT_KEY_NAME = "contents";//內容
private const string CREATEDATE = "createDate";
private const string TITLE = "title";//標題
/// <summary>
/// 目錄建立索引
/// </summary>
/// <param name="writer"></param>
/// <param name="file"></param>
public static void IndexDirectory(IndexWriter writer, io.FileInfo file)
{
if (io.Directory.Exists(file.FullName))
{
String[] files = io.Directory.GetFileSystemEntries(file.FullName);
// an IO error could occur
if (files != null)
{
for (int i = 0; i < files.Length; i++)
{
IndexDirectory(writer, new io.FileInfo(files[i])); //这里是一个递归
}
}
}
else
{
//IndexFile(file, writer);
AddHtmlDocument(file.FullName, writer);
}
}
/// <summary>
/// 單一個文件建立索引
/// </summary>
/// <param name="file"></param>
/// <param name="writer"></param>
private static void IndexFile(io.FileInfo file, IndexWriter writer)
{
Console.Out.WriteLine("adding " + file);
try
{
Document doc = new Document();
doc.Add(new Field(FILE_KEY_NAME, file.FullName, Field.Store.YES, Field.Index.ANALYZED));
doc.Add(new Field(CONTENT_KEY_NAME, new io.StreamReader(file.FullName).ReadToEnd(), Field.Store.YES, Field.Index.ANALYZED));
doc.Add(new Field(CREATEDATE,new io.FileInfo( file.FullName).LastWriteTime.ToString(), Field.Store.YES, Field.Index.ANALYZED));
//doc.Add(new Field(CONTENT_KEY_NAME, new io.StreamReader(file.FullName),Field.TermVector.WITH_OFFSETS));
writer.AddDocument(doc);
}
catch (io.FileNotFoundException fnfe)
{
}
}
public static void CreateIndex(string directory)
{
IndexWriter writer = new IndexWriter( new MMapDirectory(
new System.IO.DirectoryInfo(@"IndexDirectory\index"))
, new ChineseAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED);
IndexDirectory(writer, new System.IO.FileInfo(directory));
writer.Optimize();
writer.Dispose();
}
public static void SearchIndex(string queryString)
{
IndexSearcher indexSearcher = new IndexSearcher(new MMapDirectory(
new System.IO.DirectoryInfo(@"IndexDirectory\index")));
MultiFieldQueryParser QueryParser = new MultiFieldQueryParser(Lucene.Net.Util.Version.LUCENE_30,
new string[] { CONTENT_KEY_NAME, FILE_KEY_NAME }, new ChineseAnalyzer());
//QueryParser parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_30, CONTENT_KEY_NAME, analyzer);
Query query = QueryParser.Parse(queryString);
TopDocs docs = indexSearcher.Search(query,null,1000);
for (int i = 0; i < docs.TotalHits; i++)
{
Document doc = indexSearcher.Doc(docs.ScoreDocs[i].Doc);//得到文檔的內容
//Console.WriteLine(string.Format("文件名:{0} 內容:{1} 創建時間{2}", doc.Get(FILE_KEY_NAME),
// doc.Get(CONTENT_KEY_NAME), doc.Get(CREATEDATE)));
Console.WriteLine(string.Format("文件名:{0}", doc.Get(FILE_KEY_NAME)));
}
}
public static void AddHtmlDocument(string path, IndexWriter writer)
{
string exname = io.Path.GetExtension(path);
Document doc = new Document();
string html;
if (exname.ToLower() == ".html" || exname.ToLower() == ".htm" || exname.ToLower() == ".txt")
{
using (io.StreamReader sr = new io.StreamReader(path, System.Text.Encoding.Default))
{
html = sr.ReadToEnd();
}
}
else
{
using (io.StreamReader sr = new io.StreamReader(path, System.Text.Encoding.Unicode))
{
html = sr.ReadToEnd();
}
}
//int relativePathStartsAt = this.docRootDirectory.EndsWith("\\") ? this.docRootDirectory.Length : this.docRootDirectory.Length + 1;
//string relativePath = path.Substring(relativePathStartsAt);
//string title = io.Path.GetFileName(path);
//判断若是网页则去标签否则不用
if (exname.ToLower() == ".html" || exname.ToLower() == ".htm")
{
doc.Add(new Field(CONTENT_KEY_NAME, parseHtml(html), Field.Store.YES, Field.Index.ANALYZED));
doc.Add(new Field(TITLE, getTitle(html), Field.Store.YES, Field.Index.ANALYZED));
}
else
{
doc.Add(new Field(CONTENT_KEY_NAME, html, Field.Store.YES, Field.Index.ANALYZED));
}
doc.Add(new Field(FILE_KEY_NAME, path, Field.Store.YES, Field.Index.NO));
doc.Add(new Field(CREATEDATE, new io.FileInfo(path).LastWriteTime.ToString(), Field.Store.YES, Field.Index.ANALYZED));
writer.AddDocument(doc);
}
/**/
/// <summary>
/// 去除网页中的标签
/// </summary>
/// <param name="html">网页</param>
/// <returns>返回去除后的网页文本</returns>
private static string parseHtml(string html)
{
string temp = Regex.Replace(html, "<[^>]*>", "");
return temp.Replace(" ", " ");
}
/**/
/// <summary>
/// 获取网页标题
/// </summary>
/// <param name="html"></param>
/// <returns></returns>
private static string getTitle(string html)
{
Match m = Regex.Match(html, "<title>(.*)</title>");
if (m.Groups.Count == 2)
return m.Groups[1].Value;
return "文档标题未知";
}
}
5.使用:把要查詢的文檔放到temp下面。
代碼調用 :
LuceneFunction.CreateIndex(@"IndexDirectory\temp");
LuceneFunction.SearchIndex("Silverlight使用");
第一步創建索引,第二部查詢。
6.對於一些使用對象的說明:
61.初始化索引對象:
IndexWriter writer = new IndexWriter( new MMapDirectory(
new System.IO.DirectoryInfo(@"IndexDirectory\index"))
, new ChineseAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED);
第一個參數是目錄,即要對哪個目錄進行索引。ChineseAnalyzer是分詞類,這個使用的是中文分詞。
6.2建立索引對象后,給這個對象添加索引文件
Document doc = new Document();
doc.Add(new Field(FILE_KEY_NAME, file.FullName, Field.Store.YES, Field.Index.ANALYZED));
doc.Add(new Field(CONTENT_KEY_NAME, new io.StreamReader(file.FullName).ReadToEnd(), Field.Store.YES, Field.Index.ANALYZED));
doc.Add(new Field(CREATEDATE,new io.FileInfo( file.FullName).LastWriteTime.ToString(), Field.Store.YES, Field.Index.ANALYZED));
//doc.Add(new Field(CONTENT_KEY_NAME, new io.StreamReader(file.FullName),Field.TermVector.WITH_OFFSETS));
writer.AddDocument(doc);
Document對象,相當於數據庫中的一條記錄。
就是把Document對象寫到索引中。
doc.Add(new Field(FILE_KEY_NAME, file.FullName, Field.Store.YES, Field.Index.ANALYZED));
是相當于給這個記錄的一個字段賦值。這裡是放文件名,作為key。
doc.Add(new Field(CONTENT_KEY_NAME, new io.StreamReader(file.FullName).ReadToEnd(), Field.Store.YES, Field.Index.ANALYZED));
是對文檔內容,加入到另一個字段,建立索引。
6.3 完成上面2部,那麼會在index目錄下會由文件生成,這樣這個文件的索引建立。已經為查詢做好準備了。
6.4 建立查詢對象
IndexSearcher indexSearcher = new IndexSearcher(new MMapDirectory(
new System.IO.DirectoryInfo(@"IndexDirectory\index")));
其中目錄指向,剛才生成索引的位置。
MultiFieldQueryParser QueryParser = new MultiFieldQueryParser(Lucene.Net.Util.Version.LUCENE_30,
new string[] { CONTENT_KEY_NAME, FILE_KEY_NAME }, new ChineseAnalyzer());
指定要查詢的欄位。並且用中文分詞。
Query query = QueryParser.Parse(queryString);
生成查詢條件。
TopDocs docs = indexSearcher.Search(query,null,1000);
for (int i = 0; i < docs.TotalHits; i++)
{
Document doc = indexSearcher.Doc(docs.ScoreDocs[i].Doc);//得到文檔的內容
//Console.WriteLine(string.Format("文件名:{0} 內容:{1} 創建時間{2}", doc.Get(FILE_KEY_NAME),
// doc.Get(CONTENT_KEY_NAME), doc.Get(CREATEDATE)));
Console.WriteLine(string.Format("文件名:{0}", doc.Get(FILE_KEY_NAME)));
}
開始查詢。並且得到結果 。docs,對應這個查詢,只是查詢出索引,並沒有實際記載內容。
Document doc = indexSearcher.Doc(docs.ScoreDocs[i].Doc);
這一句,才把要的結果查詢出來了。放到Documen中,這個Documen和最上面寫入索引用的是一樣的。Documen就是查詢得到的內容。
doc.Get(FILE_KEY_NAME)是得到Document中相應欄位的數值。
7.對應html文件,可以對原有文件如果查到內容,會對相應內容,進行變色。這個就不做解釋了。
8.對於所有的文檔,只要能轉換成txt文件就都可以查詢了了。如果txt html doc pdf等。

浙公网安备 33010602011771号