Lucene4.3開發之第六步之分神中期(六)

    本篇要介紹的是關於過濾方面的知識,也就是Filter,若是瞭解Solr的朋友,確定都會知道Solr裏面fq這個參數,這個參數的做用其實就是lucene裏面的過濾,對一些q參數查詢的結果集,作過濾或者限制返回一些咱們須要的內容,能夠理解成小搜索空間的一種策略。
java

    在這裏先介紹一下查詢預過濾的區別和聯繫,其實查詢(各類Query)和過濾(各類Filter)之間很是類似,能夠這樣說,主要用Query能完成的事,用過濾也均可以完成,它們之間能夠相互轉換,最大的區別就是使用過濾返回的結果集不帶評分操做,而使用Query返回的結果都是帶相關性評分的,因此當咱們若是有一些跟評分操做沒有關係的業務,優先使用Filter操做,將會獲取更好的性能,其實這也是Solr裏面q參數和fq參數的區別。
數據庫

    下面進入正題,在這以前,先來了解lucene裏面有關於Filter的總體知識。
apache

下面,咱們看下具體的在代碼裏怎麼實現,先看下咱們的測試數據編程

id	score		bookname	ename		type	        price		date
1	1		飄渺之旅		pmzl		小說		52.23		201005		
2	1		三國演義		sgyy		小說		36.13		201207		
3	1		數據庫實戰	sjksz		技術		77.13		200811		
4	1		編程寶典		bcbd		技術		100.3		200501		
5	1		職場關係論	zcgxl		職場		36.59		200501		
6	1		健康生活		jksh		生活		20.47		200008		
7	1		看清本質		kqbz		社會		10.37		201004		
8	1		編程,編程		bcbc		社會		10.37		201004

核心代碼緩存

//使用過濾器   最後一個爲true時包含邊界部分,爲false時不包含邊界部分
//倒數第二個爲true時,包含查詢邊界,爲false時不包含
TermRangeFilter filter=new TermRangeFilter("ename", new BytesRef("h"), new BytesRef("n"), true, true);
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10000);//默認無排序方式

輸出結果app

6	1		健康生活		jksh		生活		20.47		200008		
7	1		看清本質		kqbz		社會		10.37		201004

核心代碼
ide

NumericRangeFilter<Double> filter=NumericRangeFilter.newDoubleRange("price", 10D, 40D, true, false);
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10000);//默認無排序方式

輸出結果性能

2	1		三國演義		sgyy		小說		36.13		201207		
5	1		職場關係論	zcgxl		職場		36.59		200501		
6	1		健康生活		jksh		生活		20.47		200008		
7	1		看清本質		kqbz		社會		10.37		201004		
8	1		編程,編程		bcbc		社會		10.37		201004

核心代碼測試

//使用緩存過濾
Filter filter=FieldCacheRangeFilter.newDoubleRange("price", 20D, 50D, true, true);
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10000);//默認無排序方式

輸出結果
this

2	1		三國演義		sgyy		小說		36.13		201207		
5	1		職場關係論	zcgxl		職場		36.59		200501		
6	1		健康生活		jksh		生活		20.47		200008

核心代碼

// 緩存域過濾特定的類別
Filter filter=new FieldCacheTermsFilter("type", new String[]{"技術","社會"});
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10000);//默認無排序方式

輸出結果

3	1		數據庫實戰	sjksz		技術		77.13		200811		
4	1		編程寶典		bcbd		技術		100.3		200501		
7	1		看清本質		kqbz		社會		10.37		201004		
8	1		編程,編程		bcbc		社會		10.37		201004

核心代碼

//使用QueryWrapperFilter類包裝一個Query
QueryWrapperFilter  filter=new QueryWrapperFilter(new TermQuery(new Term("type", "技術")));
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10000);//默認無排序方式

輸出結果

3	1		數據庫實戰	sjksz		技術		77.13		200811		
4	1		編程寶典		bcbd		技術		100.3		200501

如何繼承Filter基類,來定製咱們本身的Filter,自定義的Filter,雖然某些時候,功能很強大靈活,可是有幾個缺點,咱們的瞭解1,保證是內容不重複的字段,例如主鍵,若是重複,默認返回第一個做爲結果集顯示2,保證不能被分詞的內容,若是是分詞的字段,則可能會出現一些不正確的結果。

自定義Filter類

package com.sanjiesanxian.test;

import java.io.IOException;
import java.util.BitSet;

import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.index.DocsEnum;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.Filter;
import org.apache.lucene.util.AttributeSource;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.DocIdBitSet;
import org.apache.lucene.util.FixedBitSet;
import org.apache.lucene.util.OpenBitSet;

/***
 *^_^  ^_^  ^_^
 * 自定義過濾器
 * @author 三劫散仙
 * */
public class MyCustomFilter extends Filter{
	
	public MyCustomFilter() {
		// TODO Auto-generated constructor stub
	}
	
	private String[] terms;//限制返回的數據字典
	public MyCustomFilter(String ...terms) {
		// TODO Auto-generated constructor stub
		this.terms=terms;
	}
	@Override
	public DocIdSet getDocIdSet(AtomicReaderContext arg0, Bits arg1)
			throws IOException {
		//獲取沒有全部的docid包括未刪除的
		FixedBitSet bits=new FixedBitSet(arg0.reader().maxDoc())  ;
		int base=arg0.docBase;//段的相對基數,保證多個段時相對位置正確
		//int limit=base+arg0.reader().maxDoc();//計算最大限制值
		for(String s:terms){
		          //必須是惟一的不重複
			  DocsEnum doc=arg0.reader().termDocsEnum(new Term("id", s));
			  //保證是單個不重複的term,若是重複的話,默認會取第一個做爲返回結果集,分詞後的term也不適用自定義term
			  if(doc.nextDoc()!=-1){ 
			    bits.set(doc.docID());//對付符合條件約束的docid循環添加到bits裏面
				}
			  }
		return bits;
	}	
}

測試查詢代碼

MyCustomFilter filter=new MyCustomFilter("3","5","2");//隨意指定1之多個須要過濾的項
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),filter,10000);

輸出結果

2	1		三國演義		sgyy		小說		36.13		201207		
3	1		數據庫實戰	sjksz		技術		77.13		200811		
5	1		職場關係論	zcgxl		職場		36.59		200501

    自定義過濾器雖然有缺點,可是某些場景下卻能發揮很靈活的做用,特別是對沒有分詞的字段進行過濾操做。

相關文章
相關標籤/搜索