Lucene4.10使用教程(六):Lucene的過濾器
阿新 • • 發佈:2019-01-23
package com.johnny.lucene04.advance_search;
import java.io.IOException;
import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.index.DocsEnum;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermContext;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.TermRangeFilter;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.OpenBitSet;
/**
* 自定義過濾器,每次查詢都會進行過濾,所以最好做成單例,儲存在記憶體中。
* @author Johnny
*
*/
public class MyIDFilter extends Filter {
private FilterAccessor filterAccessor;
public MyIDFilter(FilterAccessor filterAccessor){
this.filterAccessor = filterAccessor;
}
/**
* 對於特價商品的Filter,可以反過來處理,將符合條件的設定為1,不符合條件的預設即可(預設為0)
*/
@Override
public DocIdSet getDocIdSet(AtomicReaderContext context, Bits acceptDocs)
throws IOException {
//openBitset是docIdSet的實現類,obs預設值都是0,0表示不顯示,1表示顯示
//獲取所有的docId
OpenBitSet obs = new OpenBitSet(context.reader().maxDoc());
//int base = context.docBase;//段的相對基數,保證多個段時相對位置正確
if(filterAccessor.hasSet()){
set(context, obs);
}else{
clear(context, obs);
}
return obs;
}
/**
* 用來設定docidset值為1,證明通過過濾
*/
private void set(AtomicReaderContext context,OpenBitSet obs){
//設定不通過過濾ID的位置的值為0
for(String id:filterAccessor.needOperateValues()){
try {
DocsEnum de = context.reader().termDocsEnum(new Term(filterAccessor.getField(),id));//必須是唯一的不重複
//保證是單個不重複的term,如果重複的話,預設會取第一個作為返回結果集,分詞後的term也不適用自定義term
if(de.nextDoc()!=-1){
obs.set(de.docID());//將符合條件的doc的值設定為1,預設為0
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 用來設定docidset值為0,證明不通過過濾
*/
private void clear(AtomicReaderContext context,OpenBitSet obs){
try{
/** //先把元素填滿 //set的值為docId,這裡設定完成後,就會將值設定為1,表示會通過過濾**/
obs.set(0,context.reader().maxDoc());
for(String id:filterAccessor.needOperateValues()){
DocsEnum de = context.reader().termDocsEnum(new Term(filterAccessor.getField(),id));//必須是唯一的不重複
//保證是單個不重複的term,如果重複的話,預設會取第一個作為返回結果集,分詞後的term也不適用自定義term
if(de.nextDoc()!=-1){
obs.clear(de.docID());;//將符合條件的doc的值設定為0,預設為1
}
}
}catch(IOException e){
e.printStackTrace();
}
}
}
測試方法:
import java.io.IOException;
import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.index.DocsEnum;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermContext;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.TermRangeFilter;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.OpenBitSet;
/**
* 自定義過濾器,每次查詢都會進行過濾,所以最好做成單例,儲存在記憶體中。
* @author Johnny
*
*/
public class MyIDFilter extends Filter {
private FilterAccessor filterAccessor;
public MyIDFilter(FilterAccessor filterAccessor){
this.filterAccessor = filterAccessor;
}
/**
* 對於特價商品的Filter,可以反過來處理,將符合條件的設定為1,不符合條件的預設即可(預設為0)
*/
@Override
public DocIdSet getDocIdSet(AtomicReaderContext context, Bits acceptDocs)
throws IOException {
//openBitset是docIdSet的實現類,obs預設值都是0,0表示不顯示,1表示顯示
//獲取所有的docId
OpenBitSet obs = new OpenBitSet(context.reader().maxDoc());
//int base = context.docBase;//段的相對基數,保證多個段時相對位置正確
if(filterAccessor.hasSet()){
set(context, obs);
}else{
clear(context, obs);
}
return obs;
}
/**
* 用來設定docidset值為1,證明通過過濾
*/
private void set(AtomicReaderContext context,OpenBitSet obs){
//設定不通過過濾ID的位置的值為0
for(String id:filterAccessor.needOperateValues()){
try {
DocsEnum de = context.reader().termDocsEnum(new Term(filterAccessor.getField(),id));//必須是唯一的不重複
//保證是單個不重複的term,如果重複的話,預設會取第一個作為返回結果集,分詞後的term也不適用自定義term
if(de.nextDoc()!=-1){
obs.set(de.docID());//將符合條件的doc的值設定為1,預設為0
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 用來設定docidset值為0,證明不通過過濾
*/
private void clear(AtomicReaderContext context,OpenBitSet obs){
try{
/** //先把元素填滿 //set的值為docId,這裡設定完成後,就會將值設定為1,表示會通過過濾**/
obs.set(0,context.reader().maxDoc());
for(String id:filterAccessor.needOperateValues()){
DocsEnum de = context.reader().termDocsEnum(new Term(filterAccessor.getField(),id));//必須是唯一的不重複
//保證是單個不重複的term,如果重複的話,預設會取第一個作為返回結果集,分詞後的term也不適用自定義term
if(de.nextDoc()!=-1){
obs.clear(de.docID());;//將符合條件的doc的值設定為0,預設為1
}
}
}catch(IOException e){
e.printStackTrace();
}
}
}
測試方法: