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等。

 

 

posted @ 2012-05-13 17:10  無限遐想  阅读(1481)  评论(3编辑  收藏  举报