記得是看了某位大蝦的blog整理的,可是現(xiàn)在也忘記了這位好人,在次表示感謝這為無名英雄.
lucene學(xué)習(xí)筆記:
(一)Query
?1.TermQuey//查詢特定的某個Field
?//過程:
?Term t = new Term("subject", "ant");
?//Term構(gòu)造函數(shù)的參數(shù):param1是Field名,param2是用戶查詢的關(guān)鍵字
?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,就會自動轉(zhuǎn)換成TermQuery.
?3.RangeQuery//范圍查詢,用于查詢范圍,通常用于時間
?//過程:
?RangeQuery query = new RangeQuery(begin, end, true);
?Hits hits = searcher.Search(query);
?//RangeQuery的第三個參數(shù)用于表示是否包含該起止日期.Lucene用[] 和{}分別表示包含和不包含.RangeQuery到QueryParse的轉(zhuǎn)化
?//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);
?//什么時候是與什么時候又是或? 關(guān)鍵在于BooleanQuery對象的Add方法的參數(shù).
?//參數(shù)一是待添加的查詢條件.
?//參數(shù)二Required表示這個條件必須滿足嗎? True表示必須滿足, False表示可以不滿足該條件.
?//參數(shù)三Prohibited表示這個條件必須拒絕嗎? True表示這么滿足這個條件的結(jié)果要排除, 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也可以.
??//默認(rèn)的情況下QueryParser會把空格認(rèn)為是或關(guān)系,就象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:僅僅是去除空格,對字符沒有l(wèi)owcase化,不支持中文
?SimpleAnalyzer:功能強于WhitespaceAnalyzer,將除去letter之外的符號全部過濾掉,并且將所有的字符lowcase化,
?不支持中文
?StopAnalyzer:StopAnalyzer的功能超越了SimpleAnalyzer,在SimpleAnalyzer的基礎(chǔ)上
??? 增加了去除StopWords的功能,不支持中文
?StandardAnalyzer:英文的處理能力同于StopAnalyzer.支持中文采用的方法為單字切分.
?ChineseAnalyzer:來自于Lucene的sand box.性能類似于StandardAnalyzer,缺點是不支持中英文混和分詞.
?CJKAnalyzer:chedong寫的CJKAnalyzer的功能在英文處理上的功能和StandardAnalyzer相同
??? 但是在漢語的分詞上,不能過濾掉標(biāo)點符號,即使用二元切分
?最強大的分析程序——StandardAnalyzer類。
?StandardAnalyzer類會將文本的所有內(nèi)容變成小寫的,并去掉一些常用的停頓詞(stop word)。
?停頓詞是像“a”、“the”和“in”這樣的詞,它們都是內(nèi)容里非常常見的詞,但是對搜索卻一點用處都沒有。
?分析程序也會分析搜索查詢,這就意味著查詢會找到匹配的部分。例如,
?這段文本“The dog is a golden retriever(這條狗是一只金毛獵犬)”,
?就會被處理為“dog golden retriever”作為索引。當(dāng)用戶搜索“a Golden Dog”的時候,
?分析程序會處理這個查詢,并將其轉(zhuǎn)變?yōu)椤癵olden dog”,這就符合我們的內(nèi)容了。
(三)性能問題
?1.切詞,索引,存屬
?域存儲字段規(guī)則
?方法 切詞 索引 存儲 用途
?Field.Text(String name, String value) 切分詞索引并存儲,比如:標(biāo)題,內(nèi)容字段
?Field.Text(String name, Reader value)? 切分詞索引不存儲,比如:META信息,
?不用于返回顯示,但需要進行檢索內(nèi)容
?Field.Keyword(String name, String value)? 不切分索引并存儲,比如:日期字段
?Field.UnIndexed(String name, String value)? 不索引,只存儲,比如:文件路徑
?Field.UnStored(String name, String value)? 只全文索引,不存儲
-----------------------------------------------------------------------------------------------
?Keywork
?該類型的數(shù)據(jù)將不被分析,而會被索引并保存保存在索引中.
?UnIndexed
?該類型的數(shù)據(jù)不會被分析也不會被索引,但是會保存在索引.
?UnStored
?和UnIndexed剛好相反,被分析被索引,但是不被保存.
?Text
?和UnStrored類似.如果值的類型為string還會被保存.如果值的類型Reader就不會被保存和UnStored一樣.
?
?2.優(yōu)化索引生成文件
??1.索引的權(quán)重SetBoost
???if (GetSenderDomain().EndsWith(COMPANY_DOMAIN))
???//如果是公司郵件,提高權(quán)重,默認(rèn)權(quán)重是1.0
?????????? doc.SetBoost(1.5);??????????????????????
???else
???//如果是私人郵件,降低權(quán)重.
?????????? doc.SetBoost(0.1);
??不僅如此你還可以對Field也設(shè)置權(quán)重.比如你對郵件的主題更感興趣.就可以提高它的權(quán)重.?
??Field senderNameField = Field.Text("senderName", senderName);
??Field subjectField = Field.Text("subject", subject);
??subjectField.SetBoost(1.2);
??2.利用IndexWriter 屬性對建立索引進行高級管理
???在建立索引的時候?qū)π阅苡绊懽畲蟮牡胤骄褪窃趯⑺饕龑懭胛募臅r候所以在具體應(yīng)用的時候就需要對此加以控制
???IndexWriter屬性??
???描述?? 默認(rèn)值???備注
???MergeFactory 10????控制segment合并的頻率和大小
???MaxMergeDocs Int32.MaxValue 限制每個segment中包含的文檔數(shù)
???MinMergeDocs 10????當(dāng)內(nèi)存中的文檔達(dá)到多少的時候再寫入segment
???Lucene默認(rèn)情況是每加入10份文檔就從內(nèi)存往index文件寫入并生成一個segement,然后每10個segment就合并成一個segment.通過MergeFactory這個變量就可以對此進行控制.
???MaxMergeDocs用于控制一個segment文件中最多包含的Document數(shù).比如限制為100的話,即使當(dāng)前有10個segment也不會合并,因為合并后的segmnet將包含1000個文檔,超過了限制.
???MinMergeDocs用于確定一個當(dāng)內(nèi)存中文檔達(dá)到多少的時候才寫入文件,該項對segment的數(shù)量和大小不會有什么影響,它僅僅影響內(nèi)存的使用,進一步影響寫索引的效率.
??3.利用RAMDirectory充分發(fā)揮內(nèi)存的優(yōu)勢
???在實際應(yīng)用中RAMDirectory和FSDirectory協(xié)作可以更好的利用內(nèi)存來優(yōu)化建立索引的時間.
???具體方法如下:
???1.建立一個使用FSDirectory的IndexWriter
???2.建立一個使用RAMDirectory的IndexWriter
???3. 把Document添加到RAMDirectory中
???4. 當(dāng)達(dá)到某種條件將RAMDirectory 中的Document寫入FSDirectory.
???5. 重復(fù)第三步
???示意代碼:
????? 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計數(shù)的方式控制何時寫入文件.
???相比之下有更大的自由性,更能提升性能.
??4.控制索引內(nèi)容的長度
???Lucene對一份文本建立索引時默認(rèn)的索引長度是10,000. 你可以通過IndexWriter 的MaxFieldLength屬性對此加以修改.還是用一個例子說明問題.
??5.Optimize 優(yōu)化
=------------------------jackstudio-----------------
posted on 2006-03-31 14:01
jackstudio 閱讀(1006)
評論(0) 編輯 收藏 所屬分類:
java