[Lucene.Net]初探免費全文檢索引擎

  • 6036
  • 0
  • C#
  • 2017-01-10

[Lucene.Net]初探免費全文檢索引擎

opensource來看Lucene.net真的讓我很敬佩,我接觸過幾家本土全文檢索廠商,

搜尋引擎+SDK整體買下來真的不便宜(不含硬體),而且有些授權方式是採取索引項目數量計算(文件一多費用相當可怕),

如果透過廠商可以100%達到企業需求(全自動無須人工介入調整)就算再貴應該還是有企業會買單,

但這情況或然率可說是0(連google都不一定有辦法達到),好比你需要建立企業領域同義字(廠商辭庫只針對一般用語),

或是調整停用字詞,其中比較讓我感冒的是建立索引過程不夠透明,

往往只顯示索引建置中等字樣,沒有提供更詳細資訊,而且建立索引過程耗時,

有時還不知道到底有沒有在執行建立,但你又不敢關閉(因為害怕又需要完整重建一次索引),

再來就是中文斷詞絕大多是採取二分法,所以還是有機會遇到找不到資料情況,

花了錢自己控制度又低的話,我會選擇不如辛苦一點使用opensource讓自己控制度高一點,

且也可依據企業需求自行調整中文斷詞(比較熱門中文分詞如MMSeg盤古),

但要使用Lucene.net當搜尋引擎前提,

你需要自行擷取各種檔案類型內文,如office相關檔案、pdf、文字檔案、msg..等(文件深度也需考慮),

我基本簡單測試一下使用標準中文斷詞,是否會有找不到資料情況。

 

1.建立索引

//檔案來源
            var _SourceFilePath = ConfigurationManager.AppSettings["SourceFilePath"].ToString();
            //索引資料庫路徑
            var _IndexPath = ConfigurationManager.AppSettings["IndexPath"].ToString();
            var dis = new DirectoryInfo(_SourceFilePath);
            var filterdis=dis.GetDirectories()
              .Where(x => ( ( !x.Attributes.HasFlag( FileAttributes.System)
                   || !x.Attributes.HasFlag(FileAttributes.Hidden) )
                   && x.Name != "LuceneIndexData"
                   && x.Name != "OpenfindIndex"
                   && x.Name != "DevTools"
                   && x.Name != "software"
                   && x.Name != "sqltmp"
                   && x.Name != "sqldatafile"
                   && x.Name != "sqlbk"
                   )).ToList<DirectoryInfo>();
            filterdis.Add(dis);//準備處理的檔案項目
            if (_LuceneHelper == null)
                _LuceneHelper = new LuceneHelper();
            int i = 1;
            //檔案類型過濾
            foreach (DirectoryInfo di in filterdis)
            {
                foreach (FileInfo fi in di.GetFiles("*.*", SearchOption.AllDirectories))                                    
                {
                    Thread.Sleep(100);
                    CurentFname = fi.FullName;
                    if ( (!fi.Attributes.HasFlag(FileAttributes.Hidden) || !fi.Attributes.HasFlag(FileAttributes.System) )
                        && ( fi.Extension.ToUpper() == ".DOCX" || fi.Extension.ToUpper() == ".DOC"
                        || fi.Extension.ToUpper() == ".PDF" || fi.Extension.ToUpper() == ".MSG"
                        || fi.Extension.ToUpper() == ".XLSX" || fi.Extension.ToUpper() == ".XLS"
                        || fi.Extension.ToUpper() == ".PPTX" || fi.Extension.ToUpper() == ".PPT"
                        || fi.Extension.ToUpper() == ".TXT"    )
                        )
                    {                     
                        _LuceneHelper.AddDocToIndex(fi);//加入索引資料庫 
                    }                  
                 }
            }

 

public bool AddDocToIndex(FileInfo fi)
        {
            var _IndexPath = ConfigurationManager.AppSettings["IndexPath"].ToString();
            FSDirectory dir = FSDirectory.Open(new DirectoryInfo(_IndexPath));
            //使用標準分詞分析(字為單位)
            Analyzer analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30);

            var indexWriter = new IndexWriter(dir, analyzer,
                                         IndexWriter.MaxFieldLength.UNLIMITED);
            var searcher = new IndexSearcher(dir, true);
            Document doc = new Document();
            // 把每一個欄位都建立索引
            Field _FId = new Field("FId", Guid.NewGuid().ToString(), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO);
            //Field _Name = new Field("Name", fi.Name, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO);
            Field _Path = new Field("Path", fi.DirectoryName, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO);
            Field _Content = new Field("Content", fi.Name + "  " + ParDoc(fi.Extension, fi.FullName), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO);
            doc.Add(_FId);
            doc.Add(_Path);
            doc.Add(_Content);
            indexWriter.AddDocument(doc);
            indexWriter.Optimize();
            indexWriter.Commit();
            indexWriter.Dispose();
            return true;
        }

 

2.搜尋

檔案內容

image

image

 

搜尋 園三結  OK

image

 

搜尋 葛亮  OK

image

 

透過Luke.net for pangu工具查看索引資料

image

 

以字為單位斷詞可說不會有找不到資料狀況,但效能還是得在更詳細測試看看,

雖然Lucene主要訴求就是快(分詞和搜尋)。

 

 

 

參考

14款中文分词开源软件【整理】

Lucene.Net ultra fast search for MVC or WebForms site => made easy!