3、Field配置所產生的效果
索引資料,簡單的代碼,只要兩個方法就搞定了,而在索引過程中用到的一些類裡最簡單,作用也不小的就是Field,接下來看看Field的各項設定都會有什麼樣的效果。
代碼 3.1
Code
1/**//// <summary>
2/// 索引資料
3/// </summary>
4private void Index()
5{
6 Analyzer analyzer = new StandardAnalyzer();
7 IndexWriter writer = new IndexWriter("IndexDirectory", analyzer, true);
8 AddDocument(writer, "我的祖國", "英語單詞");
9 AddDocument(writer, "祖國萬歲", "英語文法");
10 AddDocument(writer, "祖國", "英語單元");
11 AddDocument(writer, "人民", "單詞測試");
12 writer.Optimize();
13 writer.Close();
14}
15/**//// <summary>
16/// 為索引準備資料
17/// </summary>
18/// <param name="writer">索引執行個體</param>
19/// <param name="content">需要索引的資料</param>
20void AddDocument(IndexWriter writer, string title, string content)
21{
22 Document document = new Document();
23 document.Add(new Field("title", title, Field.Store.Yes, Field.Index.TOKENIZED));
24 document.Add(new Field("content", content, Field.Store.YES, Field.Index.TOKENIZED));
25 writer.AddDocument(document);
26}
代碼3.1就是準備好的索引過程。運行,然後呢?這裡要說到一個工具,luke(lukeall)這是一個java平台下的Lucene索引管理工具。抽空,我實現了一個簡單的dotNet版本的,詳細請查看 NLuke版本更新資訊 。接下來的索引,會用這個軟體對索引進行分析。
現在就可以開始調整AddDocument方法中Field執行個體化時的參數了,看看調整後會對索引造成什麼樣的影響。這裡以title對應的Field為例。
3.1 Field.Stroe選項
這個選項有3個值,下面來分析下效果。
3.1.1 Field.Stroe.Yes
剛好,預設的就是這個。用這選項建完索引,然後用NLuke查看,發現,title這個欄位有,而且有8個Term。切換到文檔地區,發現文檔的title有內容。這個選項表示的就是儲存,所以,這些是正常狀態。
3.1.2 Field.Stroe.No
title也有8個Term,但是文檔中沒有欄位了。也就是說現在可以用這個欄位來搜尋,但是搜尋結果Hits中,不能用Document執行個體的Get方法來取得欄位的內容了。那就是欄位內容沒有被儲存。
3.1.3 Field.Store.COMPRESS
設定為COMPRESS,報錯了,錯誤資訊“Compression support not configured”,是個配置錯誤。這個錯誤在SupportClass,CheckCompressionSupport方法被拋出。這裡讀取了一個設定檔,然後根據設定檔指定的類名來建立執行個體。這個類必須實現介面 SupportClass.CompressionSupport.ICompressionAdapter。在Lucene.Net中內建了一個“SharpZipLibAdapter”,但是需要有編譯符號SHARP_ZIP_LIB才能編譯進去。為了看看效果,所以給項目添加SHARP_ZIP_LIB符號,然後增加app.config設定檔,在appseting中添加Lucene.Net.CompressionLib.class鍵,值是SharpZipLibAdapter。然後下載 ICSharpCode.SharpZipLib.dll,這個dll才是真正實現壓縮演算法的。: http://sourceforge.net/project/downloading.php?groupname=sharpdevelop&filename=SharpZipLib_0855_Bin.zip&use_mirror=nchc
把ICSharpCode.SharpZipLib.dll引入項目,就可以使用COMPRESS這個選項了。效果與Yes是一樣的。
3.1.4 效果對比
對於Field.Stroe.Yes,產生位元組大小是:627位元組
Field.Stroe.COMPRESS是:661位元組
Field.Stroe.No是:579位元組
使用Field.Stroe.COMPRESS反而是佔用空間最大,這不符合原先的設想。那是因為我們索引的文本太小,你可以試試看增加索引的內容,再對比小效果。
3.2 Field.Index選項
現在把Field.Stroe設定為Field.Stroe.Yes,接著來看看Field.Index的效果。
3.2.1 Field.Index.TOKENIZED
這個選項是用來控制分詞的,TOKENIZED表明需要分詞。運行後title有8個Term,沒有問題。
3.2.2 Field.Index.UN_TOKENIZED
運行後只有4個Term,而且Term是原先寫入的內容,和儲存的完整內容沒有區別。
3.2.3 Field.Index.NO
和預想的一樣,title的Term一個也沒有了。
3.2.4 Field.Index.NO_NORMS
效果似乎和Field.Index.UN_TOKENIZED一樣,但是它把詞條的附加資訊全去掉了。比如,它將不再記錄詞的正太分布資料一類的東西。這樣可以減少佔用的空間。而且這個用法也有一個條件,就是只要開啟,就要全部開啟,否則會失效。比如索引了四條資料沒使用NO_NORMS,而接下來的兩條使用了NO_NORMS,那麼前面四條的資料效果,那麼接下來的兩條資料實際上並沒有產生NO_NORMS的效果。
3.2.5 效果分析
1,2,4三種情況雖然不同,但是都可以搜尋,而第三種情況,也就是設定為NO,則不可以搜尋。第一種情況,可以分詞搜尋,並且可以排序。而2,4則不能分詞搜尋,第四種情況不可以排序(不可以排序指,不能按照詞出現的頻率進行排序)。
從上面也可以看出,假設Field.Store設定為NO,而Field.Index也設定為NO,那就和沒添加是一樣的了。Field.Store是給你取完整資料用的,而Field.Index則是給搜尋用的。在極端的情況下,可以設定Field.Store為NO,而Field.Index可以搜尋,等取資料的時候再從資料來源(比如資料庫),它們中間有個關聯法則,那樣可以有效減輕Lucene的工作壓力。
3.3 Field.TermVector
Field.TermVector選項,現在工具還沒實現這個功能,不過可以自己編碼來實現。
代碼 3.3.5.1
Code
1[Test]
2public void TermVectorTest()
3{
4 IndexReader reader = IndexReader.Open("IndexDirectory");
5 int numDoc = reader.NumDocs();
6 for (int i = 0; i < numDoc; i++)
7 {
8 Console.WriteLine("Doc:#" + i + "----------------------------");
9 Document doc = reader.Document(i);
10 Field field = doc.GetField("title");
11 Console.WriteLine("是否被索引:" + field.IsIndexed());
12 Console.WriteLine("是否被儲存:" + field.IsStored());
13 Console.WriteLine("是否儲存開始位置:" + field.IsStorePositionWithTermVector());
14 Console.WriteLine("是否儲存結束位置:" + field.IsStoreOffsetWithTermVector());
15 Console.WriteLine("是否儲存了向量:" + field.IsTermVectorStored());
16 Console.WriteLine("是否分詞:" + field.IsTokenized());
17 Console.WriteLine("--------------------------------------------");
18 }
19 reader.Close();
20}
設定Field.TermVector後,可以用代碼3.3.5.1檢查效果。你可以自己去試試。