1. 程式人生 > >Lucene4.10使用教程(六):Lucene的過濾器

Lucene4.10使用教程(六):Lucene的過濾器

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();
        }
    }

}

測試方法: