業務場景:
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>