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