記得是看了某位大蝦的blog整理的,可是現在也忘記了這位好人,在次表示感謝這為無名英雄.
lucene學習筆記:
(一)Query
?1.TermQuey//查詢特定的某個Field
?//過程:
?Term t = new Term("subject", "ant");
?//Term構造函數的參數:param1是Field名,param2是用戶查詢的關鍵字
?Query query = new TermQuery(t);
?Hits hits = searcher.Search(query);
?2.QueryParse//簡化查詢語句
?//過程:
?Query query = QueryParser.Parse("+JUNIT +ANT -MOCK","contents",new SimpleAnalyzer());
?Hits hits = searcher.Search(query);
?//注意:TermQuery和QueryParse只要在QueryParse的Parse方法中只有一個word,就會自動轉換成TermQuery.
?3.RangeQuery//范圍查詢,用于查詢范圍,通常用于時間
?//過程:
?RangeQuery query = new RangeQuery(begin, end, true);
?Hits hits = searcher.Search(query);
?//RangeQuery的第三個參數用于表示是否包含該起止日期.Lucene用[] 和{}分別表示包含和不包含.RangeQuery到QueryParse的轉化
?//Query query = QueryParser.Parse("pubmonth:[200004 TO 200206]", "subject", new SimpleAnalyzer());
?//IndexSearcher searcher = new IndexSearcher(directory);
?//Hits hits = searcher.Search(query);
?4.PrefixQuery//搜索是否包含某個特定前綴
?PrefixQuery query = new PrefixQuery(new Term("category", "/Computers"));
?Hits hits = searcher.Search(query);
?5.BooleanQuery//用于測試滿足多個條件
?TermQuery searchingBooks =new TermQuery(new Term("subject", "junit"));
?RangeQuery currentBooks =new RangeQuery(new Term("pubmonth", "200301"),new Term("pubmonth", "200312"),true);
?BooleanQuery currentSearchingBooks = new BooleanQuery();
?currentSearchingBooks.Add(searchingBooks, true, false);
?currentSearchingBooks.Add(currentBooks, true, false);
?IndexSearcher searcher = new IndexSearcher(directory);
?Hits hits = searcher.Search(currentSearchingBooks);
?//什么時候是與什么時候又是或? 關鍵在于BooleanQuery對象的Add方法的參數.
?//參數一是待添加的查詢條件.
?//參數二Required表示這個條件必須滿足嗎? True表示必須滿足, False表示可以不滿足該條件.
?//參數三Prohibited表示這個條件必須拒絕嗎? True表示這么滿足這個條件的結果要排除, False表示可以滿足該條件.
?//BooleanQuery和QueryParse
?[Test]
???????? public void TestQueryParser()
???????? {
????????????? Query query = QueryParser.Parse("pubmonth:[200301 TO 200312] AND junit", "subject", new SimpleAnalyzer());
????????????? IndexSearcher searcher = new IndexSearcher(directory);
????????????? Hits hits = searcher.Search(query);
????????????? Assert.AreEqual(1, hits.Length());
????????????? query = QueryParser.Parse("/Computers/JUnit OR /Computers/Ant", "category", new WhitespaceAnalyzer());
????????????? hits = searcher.Search(query);
????????????? Assert.AreEqual(2, hits.Length());
???????? }
??//注意AND和OR的大小 如果想要A與非B 就用 A AND –B 表示, +A –B也可以.
??//默認的情況下QueryParser會把空格認為是或關系,就象google一樣.但是你可以通過QueryParser對象修改這一屬性.
[Test]
???????? public void TestQueryParserDefaultAND()
???????? {
????????????? QueryParser qp = new QueryParser("subject", new SimpleAnalyzer());
????????????? qp.SetOperator(QueryParser.DEFAULT_OPERATOR_AND );
????????????? Query query = qp.Parse("pubmonth:[200301 TO 200312] junit");
????????????? IndexSearcher searcher = new IndexSearcher(directory);
????????????? Hits hits = searcher.Search(query);
????????????? Assert.AreEqual(1, hits.Length());
???????? }
?6.PhraseQuery//短語查詢
?7.WildcardQuery//通配符搜索
?8.FuzzyQuery//模糊查詢
(二)Analyzer
?WhitespaceAnalyzer:僅僅是去除空格,對字符沒有lowcase化,不支持中文
?SimpleAnalyzer:功能強于WhitespaceAnalyzer,將除去letter之外的符號全部過濾掉,并且將所有的字符lowcase化,
?不支持中文
?StopAnalyzer:StopAnalyzer的功能超越了SimpleAnalyzer,在SimpleAnalyzer的基礎上
??? 增加了去除StopWords的功能,不支持中文
?StandardAnalyzer:英文的處理能力同于StopAnalyzer.支持中文采用的方法為單字切分.
?ChineseAnalyzer:來自于Lucene的sand box.性能類似于StandardAnalyzer,缺點是不支持中英文混和分詞.
?CJKAnalyzer:chedong寫的CJKAnalyzer的功能在英文處理上的功能和StandardAnalyzer相同
??? 但是在漢語的分詞上,不能過濾掉標點符號,即使用二元切分
?最強大的分析程序——StandardAnalyzer類。
?StandardAnalyzer類會將文本的所有內容變成小寫的,并去掉一些常用的停頓詞(stop word)。
?停頓詞是像“a”、“the”和“in”這樣的詞,它們都是內容里非常常見的詞,但是對搜索卻一點用處都沒有。
?分析程序也會分析搜索查詢,這就意味著查詢會找到匹配的部分。例如,
?這段文本“The dog is a golden retriever(這條狗是一只金毛獵犬)”,
?就會被處理為“dog golden retriever”作為索引。當用戶搜索“a Golden Dog”的時候,
?分析程序會處理這個查詢,并將其轉變為“golden dog”,這就符合我們的內容了。
(三)性能問題
?1.切詞,索引,存屬
?域存儲字段規則
?方法 切詞 索引 存儲 用途
?Field.Text(String name, String value) 切分詞索引并存儲,比如:標題,內容字段
?Field.Text(String name, Reader value)? 切分詞索引不存儲,比如:META信息,
?不用于返回顯示,但需要進行檢索內容
?Field.Keyword(String name, String value)? 不切分索引并存儲,比如:日期字段
?Field.UnIndexed(String name, String value)? 不索引,只存儲,比如:文件路徑
?Field.UnStored(String name, String value)? 只全文索引,不存儲
-----------------------------------------------------------------------------------------------
?Keywork
?該類型的數據將不被分析,而會被索引并保存保存在索引中.
?UnIndexed
?該類型的數據不會被分析也不會被索引,但是會保存在索引.
?UnStored
?和UnIndexed剛好相反,被分析被索引,但是不被保存.
?Text
?和UnStrored類似.如果值的類型為string還會被保存.如果值的類型Reader就不會被保存和UnStored一樣.
?
?2.優化索引生成文件
??1.索引的權重SetBoost
???if (GetSenderDomain().EndsWith(COMPANY_DOMAIN))
???//如果是公司郵件,提高權重,默認權重是1.0
?????????? doc.SetBoost(1.5);??????????????????????
???else
???//如果是私人郵件,降低權重.
?????????? doc.SetBoost(0.1);
??不僅如此你還可以對Field也設置權重.比如你對郵件的主題更感興趣.就可以提高它的權重.?
??Field senderNameField = Field.Text("senderName", senderName);
??Field subjectField = Field.Text("subject", subject);
??subjectField.SetBoost(1.2);
??2.利用IndexWriter 屬性對建立索引進行高級管理
???在建立索引的時候對性能影響最大的地方就是在將索引寫入文件的時候所以在具體應用的時候就需要對此加以控制
???IndexWriter屬性??
???描述?? 默認值???備注
???MergeFactory 10????控制segment合并的頻率和大小
???MaxMergeDocs Int32.MaxValue 限制每個segment中包含的文檔數
???MinMergeDocs 10????當內存中的文檔達到多少的時候再寫入segment
???Lucene默認情況是每加入10份文檔就從內存往index文件寫入并生成一個segement,然后每10個segment就合并成一個segment.通過MergeFactory這個變量就可以對此進行控制.
???MaxMergeDocs用于控制一個segment文件中最多包含的Document數.比如限制為100的話,即使當前有10個segment也不會合并,因為合并后的segmnet將包含1000個文檔,超過了限制.
???MinMergeDocs用于確定一個當內存中文檔達到多少的時候才寫入文件,該項對segment的數量和大小不會有什么影響,它僅僅影響內存的使用,進一步影響寫索引的效率.
??3.利用RAMDirectory充分發揮內存的優勢
???在實際應用中RAMDirectory和FSDirectory協作可以更好的利用內存來優化建立索引的時間.
???具體方法如下:
???1.建立一個使用FSDirectory的IndexWriter
???2.建立一個使用RAMDirectory的IndexWriter
???3. 把Document添加到RAMDirectory中
???4. 當達到某種條件將RAMDirectory 中的Document寫入FSDirectory.
???5. 重復第三步
???示意代碼:
????? private FSDirectory fsDir = FSDirectory.GetDirectory("index",true);?
?????? private RAMDirectory ramDir = new RAMDirectory();
?????? private IndexWriter fsWriter = IndexWriter(fsDir,new SimpleAnalyzer(), true);
?????? private IndexWriter ramWriter = new IndexWriter(ramDir,new SimpleAnalyzer(), true);
?????? while (there are documents to index)
????? {
???????? ramWriter.addDocument(doc);
???????? if (condition for flushing memory to disk has been met)
???????? {
?????????? fsWriter.AddIndexes(Directory[]{ramDir}) ;
?????????? ramWriter.Close();????????? //why not support flush?
?????????? ramWriter =new IndexWriter(ramDir,new SimpleAnalyzer(),true);
???????? }
???? }
???這里的條件完全由用戶控制,而不是FSDirectory采用對Document計數的方式控制何時寫入文件.
???相比之下有更大的自由性,更能提升性能.
??4.控制索引內容的長度
???Lucene對一份文本建立索引時默認的索引長度是10,000. 你可以通過IndexWriter 的MaxFieldLength屬性對此加以修改.還是用一個例子說明問題.
??5.Optimize 優化
=------------------------jackstudio-----------------