Lucene4.10使用教程(六):Lucene的过滤器

过滤器在生产环境中应用也比较多。比如禁用词的过滤显示、推荐商品的过期设置等。

在编写时,需要在incrementToken添加自己的过滤规则。,下面的demo是针对同义词编写的过滤。过滤器的编写也可以参照org.apache.lucene.analysis.cn.ChineseFilter进行编写。

使用自定义过滤器进行查询

package com.johnny.lucene04.advance_search;

import java.io.IOException;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;

public class CustomFilter {
/**
 * 用户自定义Filter,通过Filter进行数据过滤,在这里可以通过ioc注入方式或者配置文件的方式针对多种情况添加不通的过滤器
 */
    public void searchByCustomFilter(){
        try {
            IndexSearcher search = new IndexSearcher(DirectoryReader.open(FileIndexUtils.getDirectory()));
            Query q = new TermQuery(new Term("content","java"));
            TopDocs tds = search.search(q, new MyIDFilter(new FilterAccessor() {

                @Override
                public String[] needOperateValues() {
                    /**显示ID
                    String[] ids = new String[]{"1","2","3","4","5"};
                    return ids;
                    **/
                    /**按照fileName进行展示**/
                    String[] fileNames = new String[]{"MySameAnalyzer.txt","MySameAnalyzer副本 13.txt"};
                    return fileNames;
                }

                @Override
                public String getField() {
                /**    String field = "id"; **/
                    String field = "fileName";
                    return field;
                }

                @Override
                public boolean hasSet() {
                    return true;
                }
                
            }),200);
            for(ScoreDoc sd:tds.scoreDocs) {
                Document d = search.doc(sd.doc);
                System.out.println(sd.doc+":("+sd.score+")" +
                        "["+d.get("fileName")+"【"+d.get("path")+"】--->"+
                        d.get("size")+"------------>"+d.get("id"));
            }
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

package com.johnny.lucene04.advance_search;
/**
 * 定义数据处理的接口,用来提高数据处理的通用性
 * 使用情况参见customFilter和MyIdFilter
 * @author Johnny
 *
 */
public interface FilterAccessor {
    public String[] needOperateValues();//获取需要处理的元素
    
    public String getField();//需要进行过滤的字段(也就是所谓的域)
    /**
     * 如果返回值为true,表示needOperateValues需要进行显示,
     * 如果返回值为false,表示needOperateValues需要进行隐藏
     **/
    public boolean hasSet();//设定需要处理的数据是否通过过滤
}
自定义过滤器
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();
        }
    }

}

测试方法:
@Test
    public void testCustomFilter(){
        CustomFilter cf = new CustomFilter();
        cf.searchByCustomFilter();
    }


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值