[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.搜尋
檔案內容
搜尋 園三結 OK
搜尋 葛亮 OK
透過Luke.net for pangu工具查看索引資料
以字為單位斷詞可說不會有找不到資料狀況,但效能還是得在更詳細測試看看,
雖然Lucene主要訴求就是快(分詞和搜尋)。
參考