lucene自定义过滤器Filter

本文探讨了在Lucene中利用自定义过滤器避免频繁重构索引的方法,通过OpenBitSet实现高效过滤,优化查询性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

业务场景:
  1:假设数据库中的字段给删了,如果 重建索引的话,就开销比较大。这个时候就可以考虑自定义过滤器

  2:控制部分查询权限


为了避免频繁重构索引,我们可以在查询的时候定义一个自己的过滤器 ,去过滤掉这些数据。

lucene在package org.apache.lucene.util; 这包中提供了一个非常好的DocIdSet 实现类OpenBitSet,OpenBitSet这个实现类用来保存 0,1,1,0,0,1 ;每个0 、1  对应着其文档docid。呈现这样的链装结构表


大概实现原理通过继承Filter,重写其getDocIdSet方法。。。通过返回实现类OpenBitSet的对象。这个对象通过不用的业务需求,把不同的文档docid,绑定 0,1 序列。


通过以下方法,只需要提供文档id就直接把0----》1:


代码:

<span style="font-size:14px;">
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.Filter;
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;
import org.apache.lucene.util.OpenBitSet;

public class CustomQueryFilter  extends Filter{
	
	
	private FilterAccessFactory filterAccessFactory;
	
	public CustomQueryFilter(FilterAccessFactory filterAccessFactory){
		this.filterAccessFactory=filterAccessFactory;
	}

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Override
	public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
		/**
		 * 创建一个bit
		 * 假设索引库中有1W条数据,那么 就有1W的长度
		 * bit里面都是保存0和1 的数据
		 * 刚创建的时候,默认全部为0;
		 */
		OpenBitSet obs=new OpenBitSet(reader.maxDoc());
		//把元素全部设置为1
		obs.set(0,reader.maxDoc());
		
		/**
		 * 方式一
		 * 两次循环,性能较差
		 */
//		IndexSearcher searcher=new  IndexSearcher(reader);
//		TopDocs tds=searcher.search(new TermQuery(new Term("content","name")), 500);
//		for(ScoreDoc doc:tds.scoreDocs){
//			for(String id:filterAccessFactory.values()){			
//				if(doc.doc==Integer.parseInt(id)){
//					obs.clear(Integer.parseInt(id));
//					System.out.println("-----------去除id---------------"+id);
//				}
//			}
//		}
//		searcher.close();
		
		/**
		 * 方式二
		 */
		int[] docs=new int[1];
		int[] freqs=new int[1];
		for(String id:filterAccessFactory.values()){
			TermDocs tdocs=reader.termDocs(new Term(filterAccessFactory.getField(), id));
			//会把查询出来的对象位置保存到docs中,出现的频率信息保存到freqs中,放回获取的条数
			int count=tdocs.read(docs, freqs);
			if(count==1){
				obs.clear(docs[0]);
				System.out.println("-----------去除id---------------"+id);
			}
		}
		return obs;
	}

	/**
	 * 测试
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			IndexSearcher searcher = new IndexSearcher(IndexReader.open(FileIndexUtils.getDirectory()));
			Query query = new TermQuery(new Term("content","name"));
			TopDocs tds = searcher.search(query,new CustomQueryFilter(new FilterAccessFactory(){
				@Override
				public boolean addOrUpdate() {
					return true;
				}
				@Override
				public String getField() {
					return "id";
				}
				@Override
				public String[] values() {
					return new String[]{"1","5","3","4"};
				}
			}),500);
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
			for(ScoreDoc sd:tds.scoreDocs) {
				Document d = searcher.doc(sd.doc);
				System.out.println(sd.doc+":("+sd.score+")" +
						"["+d.get("filename")+"路径:"+d.get("path")+"--->"+
						d.get("size")+"-----"+sdf.format(new Date(Long.valueOf(d.get("date"))))+"]");
			}
			searcher.close(); 
		} catch (NumberFormatException e) {
			e.printStackTrace();
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
</span>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值