Lucene.net準系統核心代碼

來源:互聯網
上載者:User

1. 基本應用


using System;
using System.Collections.Generic;
using System.Text;
using Lucene.Net;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.QueryParsers;
using Lucene.Net.Search;
using Lucene.Net.Store;
using Lucene.Net.Util;

 

namespace ConsoleApplication1.Lucene
{
   public class LuceneTest
   {
     private const string FieldName = “name”;
     private const string FieldValue = “value”;

    
private Directory directory = new RAMDirectory();
     private Analyzer analyzer = new
StandardAnalyzer();

     public
LuceneTest()
     {
     }

    
private void Index()
     {
       IndexWriter writer = new
IndexWriter(directory, analyzer, true);
       writer.maxFieldLength = 1000;
     
       for (int i = 1; i <= 100; i++)
       {
         Document document = new
Document();

        
document.Add(new Field(FieldName, “name” + i,
Field.Store.YES, Field.Index.UN_TOKENIZED));
         document.Add(new
Field(FieldValue, “Hello, World!”,
Field.Store.YES, Field.Index.TOKENIZED));

        
writer.AddDocument(document);
       }

      
writer.Optimize();
       writer.Close();
     }

    
private void Search()
     {
       Query query = QueryParser.Parse(“name*”,
FieldName, analyzer);

      
IndexSearcher searcher = new IndexSearcher(directory);

       Hits
hits = searcher.Search(query);
     
       Console.WriteLine(“符合條件記錄:{0}; 索引庫記錄總數:{1}”,
hits.Length(), searcher.Reader.NumDocs());
       for (int i = 0; i <
hits.Length(); i++)
       {
         int docId = hits.Id(i);
         string name =
hits.Doc(i).Get(FieldName);
         string value =
hits.Doc(i).Get(FieldValue);
         float score = hits.Score(i);

        
Console.WriteLine(“{0}: DocId:{1}; Name:{2};
Value:{3}; Score:{4}”,
           i + 1, docId, name, value,
score);
       }

      
searcher.Close();
     }
   }
}

除了
RAMDirectory,還可以使用
FSDirectory。(注意 FSDirectory.GetDirectory 的 create 參數,為 true 時將刪除已有索引庫檔案,可以通過 IndexReader.IndexExists() 方法判斷。)

從指定目錄開啟已有索引庫。

private Directory directory =
FSDirectory.GetDirectory(“c:\index”, false);

將索引庫載入記憶體,以提高搜尋速度。

private Directory directory = new
RAMDirectory(FSDirectory.GetDirectory(@”c:\index”, false));
//或
//private Directory directory = new RAMDirectory(c:\index”);

2. 多欄位搜尋

使用 MultiFieldQueryParser
可以指定多個搜尋欄位。

Query query = MultiFieldQueryParser.Parse(“name*”, new
string[] { FieldName, FieldValue }, analyzer);

 

IndexReader reader = IndexReader.Open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
Hits hits = searcher.Search(query);

3. 多條件搜尋

除了使用
QueryParser.Parse 分解複雜的搜尋文法外,還可以通過組合多個 Query 來達到目的。

Query query1 = new TermQuery(new Term(FieldValue,
“name1″)); // 詞語搜尋
Query query2 = new WildcardQuery(new Term(FieldName, “name*”)); // 萬用字元
//Query query3 = new PrefixQuery(new Term(FieldName, “name1″)); // 欄位搜尋 Field:Keyword,自動在結尾添加 *
//Query query4 = new RangeQuery(new Term(FieldNumber,
NumberTools.LongToString(11L)), new Term(FieldNumber,
NumberTools.LongToString(13L)), true); // 範圍搜尋
//Query query5 = new FilteredQuery(query, filter); // 帶過濾條件的搜尋
     
BooleanQuery query = new BooleanQuery();
query.Add(query1, BooleanClause.Occur.MUST);
query.Add(query2, BooleanClause.Occur.MUST);

 

IndexSearcher searcher = new
IndexSearcher(reader);
Hits hits = searcher.Search(query);

4. 設定權重

可以給 Document 和 Field 增加權重(Boost),使其在搜尋結果排名更加靠前。預設情況下,搜尋結果以
Document.Score 作為排序依據,該數值越大排名越靠前。Boost 預設值為 1。

Score = Score * Boost

通過上面的公式,我們就可以設定不同的權重來影響排名。

如下面的例子中根據 VIP 層級設定不同的權重。

Document document = new Document();
switch (vip)
{
   case VIP.Gold: document.SetBoost(2F);
break;
   case VIP.Argentine:
document.SetBoost(1.5F); break;
}

只要 Boost 足夠大,那麼就可以讓某個命中結果永遠排第一位,這就是百度等網站的”收費排名”業務。明顯有失公平,鄙視一把。

5. 排序

通過 SortField
的構造參數,我們可以設定排序欄位,排序條件,以及倒排。

Sort sort = new Sort(new SortField(FieldName,
SortField.DOC, false));

 

IndexSearcher searcher = new
IndexSearcher(reader);
Hits hits = searcher.Search(query, sort);

排序對搜尋速度影響還是很大的,儘可能不要使用多個排序條件。

6. 過濾

使用 Filter 對搜尋結果進行過濾,可以獲得更小範圍內更精確的結果。

舉個例子,我們搜尋上架時間在 2005-10-1

2005-10-30 之間的商品。
對於日期時間,我們需要轉換一下才能添加到索引庫,同時還必須是索引欄位。

// index
document.Add(FieldDate, DateField.DateToString(date), Field.Store.YES,
Field.Index.UN_TOKENIZED);

 

//…

// search
Filter filter = new DateFilter(FieldDate, DateTime.Parse(“2005-10-1″),
DateTime.Parse(“2005-10-30″));
Hits hits = searcher.Search(query, filter);

除了日期時間,還可以使用整數。比如搜尋價格在 100 ~ 200
之間的商品。
Lucene.Net NumberTools 對於數字進行了補位處理,如果需要使用浮點數可以自己參考源碼進行。

// index
document.Add(new Field(FieldNumber, NumberTools.LongToString((long)price),
Field.Store.YES, Field.Index.UN_TOKENIZED));

 

//…

// search
Filter filter = new RangeFilter(FieldNumber, NumberTools.LongToString(100L),
NumberTools.LongToString(200L), true, true);
Hits hits = searcher.Search(query, filter);

使用 Query 作為過濾條件。

QueryFilter filter = new
QueryFilter(QueryParser.Parse(“name2″,
FieldValue, analyzer));

我們還可以使用
FilteredQuery 進行多條件過濾。

Filter filter = new DateFilter(FieldDate,
DateTime.Parse(“2005-10-10″),
DateTime.Parse(“2005-10-15″));
Filter filter2 = new RangeFilter(FieldNumber, NumberTools.LongToString(11L),
NumberTools.LongToString(13L), true, true);

 

Query query = QueryParser.Parse(“name*”,
FieldName, analyzer);
query = new FilteredQuery(query, filter);
query = new FilteredQuery(query, filter2);

IndexSearcher searcher = new
IndexSearcher(reader);
Hits hits = searcher.Search(query);

7. 分布搜尋

我們可以使用
MultiReader 或
MultiSearcher 搜尋多個索引庫。

MultiReader reader = new MultiReader(new
IndexReader[] { IndexReader.Open(@”c:\index”),
IndexReader.Open(@”\\server\index”) });
IndexSearcher searcher = new IndexSearcher(reader);
Hits hits = searcher.Search(query);

IndexSearcher searcher1 = new
IndexSearcher(reader1);
IndexSearcher searcher2 = new IndexSearcher(reader2);
MultiSearcher searcher = new MultiSearcher(new Searchable[] { searcher1,
searcher2 });
Hits hits = searcher.Search(query);

還可以使用
ParallelMultiSearcher 進行多線程並行搜尋。

8. 合并索引庫


directory1 合并到
directory2 中。

Directory directory1 = FSDirectory.GetDirectory(“index1″, false);
Directory directory2 = FSDirectory.GetDirectory(“index2″, false);

 

IndexWriter writer = new IndexWriter(directory2,
analyzer, false);
writer.AddIndexes(new Directory[] { directory });
Console.WriteLine(writer.DocCount());
writer.Close();

9. 顯示搜尋文法字串

我們組合了很多種搜尋條件,或許想看看與其對等的搜尋文法串是什麼樣的。

BooleanQuery query = new BooleanQuery();
query.Add(query1, true, false);
query.Add(query2, true, false);
//…

 

Console.WriteLine(“Syntax:
{0}”, query.ToString());

輸出:
Syntax: +(name:name* value:name*) +number:[0000000000000000b TO 0000000000000000d]

呵呵,就這麼簡單。

10. 操作索引庫

刪除 (虛刪除,僅添加了刪除標記。調用
IndexWriter.Optimize() 後真正刪除。)

IndexReader reader = IndexReader.Open(directory);

 

// 刪除指定序號(DocId)的 Document。
reader.Delete(123);

// 刪除包含指定 Term 的 Document。
reader.Delete(new Term(FieldValue, “Hello”));

// 恢複虛刪除。
reader.UndeleteAll();

reader.Close();

累加式更新 (只需將 create 參數設為 false,即可往現有索引庫添加新資料。)

Directory directory = FSDirectory.GetDirectory(“index”, false);
IndexWriter writer = new IndexWriter(directory, analyzer, false);
writer.AddDocument(doc1);
writer.AddDocument(doc2);
writer.Optimize();
writer.Close();

11. 最佳化

批量向
FSDirectory 增加索引時,增大合并因子(mergeFactor
)和最小文檔合并數(minMergeDocs)有助於提高效能,減少索引時間。

IndexWriter writer = new IndexWriter(directory,
analyzer, true);

 

writer.maxFieldLength = 1000; // 欄位最大長度
writer.mergeFactor = 1000;
writer.minMergeDocs = 1000;

for (int i = 0; i < 10000; i++)
{
   // Add Documentes…
}

writer.Optimize();
writer.Close();

 

---恢複內容結束---

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.