2012-10-04

[C#]Lucene.net–使用RAMDirectory、 優化Index

 

過去介紹過如何透過 Lucene.net 去製作 index ..

其中我所使用的都是..

FSDirectory dir = FSDirectory.Open(new DirectoryInfo("Index 目錄"));

但是其實有一種方法可以加快,製作 index 的速度也就是  RAMDirectory



C# Code :



static RAMDirectory mDirectory = new RAMDirectory();
 
protected void btnCreateIndexToRam_Click(object sender, EventArgs e)
{
    Stopwatch sw = new Stopwatch();
 
    // 讀取所有資料
    var di = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory + "\\Source\\");
 
    sw.Start();
    var allObjects = di.GetFiles().Select(
        x => JObject.Parse((File.ReadAllText(x.FullName)))).ToArray();
 
    //Index 存放路徑
    string indexPath = AppDomain.CurrentDomain.BaseDirectory + "\\Index1\\";
 
  
 
    //IndexWriter
    IndexWriter indexWriter = new IndexWriter(mDirectory, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29), true, IndexWriter.MaxFieldLength.UNLIMITED);
 
    // 還原且加入需做 index 的欄位
    foreach (JObject ds in allObjects)
    {
 
        Document doc = new Document();
        // 把每一個欄位都建立索引
        Field f_Id = new Field("Id", ds["Id"].ToString(), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO);
        Field f_Age = new Field("Age", ds["Age"].ToString(), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO);
        Field f_Memo = new Field("Memo", ds["Memo"].ToString(), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO);
        Field f_BirthDay = new Field("BirthDay", DateTime.Parse(ds["Birthday"].ToString()).ToString("yyyyMMdd"), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO);
        doc.Add(f_Id); doc.Add(f_Age); doc.Add(f_Memo); doc.Add(f_BirthDay);
 
        indexWriter.AddDocument(doc);
    }
 
    indexWriter.Optimize();
    indexWriter.Commit();
    indexWriter.Close();
    sw.Stop();
 
    Response.Write("花費時間: " + sw.Elapsed + "");
}

之所以會放在外面宣告成 Static 是因為我撰寫的環境都是 ASP.net 如果不這樣做,會消失…


到底透過記憶製作會比較快嗎?!


我的電腦是 SSD 硬碟 記憶體為 8G..


使用 FSDirectory 效果大致上我測試都是 40~60 秒之間


但是使用 RAMDirectory 鮮少高於 40 秒..


如果 index 在 RAM 裡面我如何讀取搜尋呢?!


 


C# Code :


 



protected void btnSearchFromRAM_Click(object sender, EventArgs e)
{
    // 啟用監看
    Stopwatch sw = new Stopwatch();
    sw.Start();
 
 
    IndexSearcher search = new IndexSearcher(mDirectory, true);
    // 針對 Memo 欄位進行搜尋
    QueryParser parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_29, "Memo", new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29));
    // 搜尋的關鍵字
    Query query = parser.Parse(txtKeyword.Text);
    // 開始搜尋
    var hits = search.Search(query, null, search.MaxDoc()).ScoreDocs;
 
    sw.Stop();
    Response.Write("花費時間:" + sw.Elapsed + "<br /><hr />");
    Response.Write("資料比數:" + hits.Length + "<br /><hr />");
    Response.Write("Result:<br />");
 
    foreach (var res in hits)
    {
        // 支援 Lucene.net 3.0 的做法
        Response.Write("Id:" + search.Doc(res.doc).Get("Id") + "  Memo=" + search.Doc(res.doc).Get("Memo").ToString().Replace(txtKeyword.Text, "<span style='color:red'>" + txtKeyword.Text + "</span>") + "<br />");
    }
}