lucene-搜索过滤
1、使用过滤可以缩小搜索空间,把可能的搜索匹配结果限制在所有文档的一个子集中。
2、内置了三个Filter子类:
1)DateFilter使搜索只限于指定的日期域的值在某一时间范围内的文档空间里
2)QueryFilter把查询结果做为另一个新查询可搜索的文档空间
3)CachingWrappperFilter是其他过滤器的装饰器,将结果缓存起来以便再次使用,从而提高性能。
3、DateFiler
此过滤器仅过滤,但不能缓存,如果重复使用DateFilter,Lucene每次都会重新进行日期过滤.导致性能下降.
下例中modified域索引为Keyword
public class FilterTest extends testcase{
privateQuery allBooks;
privateIndexsearcher searcher;
privateint numAllBooks;
protectedvoid setUp() throws Exception{
super.setUp();
allBooks=new RangeQuery(new Term("pubmonth","190001"),newTerm("pubmonth","200512"),true);
searcher=new IndexSearcher(directory);
Hits hits=searcher.search(allBooks);
numAllBooks=hits.length();
}
publicvoid testDateFilter() throws Exception{
Datejan1=parseDate("2004 Jan 01");
Date jan31=parseDate("2004 Jan 31");
Date dec31=parseDate("2004 Dec 31");
//过滤指定日期范围
DateFilter filter=new DateFilter("modified",jan1,dec31);
Hits hits=searcher.search(allBooks,filter);
assertEquals("all modified in 2004",numAllBooks,hits.length());
//过滤某一端日期边界不确定,使用静态方法
filter=DateFilter.Before("modified",jan31);//在jan31结束的结果
filter=DateFilter.After("modified",jan31);//从jan31开始的结果
}
}
4、QueryFilter
提供缓存功能,做为过滤结果将被缓存起来,以后使用同一个QueryFilter对象或IndexSearcher对象进行搜索时,优化性能。
public void testQueryFilter() throwsException{
TermQuery categoryQuery=new TermQuery(newTerm("category","/philosophy/eastern"));
FiltercategoryFilter=newQueryFilter(categoryQuery);
Hits hits=searcher.search(allBooks,categoryFilter);
}
下面使用QueryFilter完成DateFilter功能,并且具有缓存功能
public voidtestQueryFilterRange() throws Exception{
Date jan1=parseDate("2004 Jan01");//返回date对象;
Date dec31=parseDate("2004 Dec 31");
Termstart=newTerm("modified",DateField.dateToString(jan1));
Termend=newTerm("modified",DateField.dateToString(dec31));
QueryrangeQuery=new RangeQuery(start,end,true);
Filter filter=newQueryFilter(rangeQuery);
Hits hits=searcher.search(allBooks,filter);
}
下面使用QueryFilter完成通过过滤器使搜索结果文档限定在指定范围内
public void testrangefilter throwsException{
directory=new RAMDirectory();
setUp();
TermQuery query=new TermQuery(new Term("kword","info"));
IndexSearcher searcher=new IndexSearcher(directory);
Hitshits=searcher.search(query);//所以kword域含info的文档
QueryFilter jakeFilter=new QueryFilter(new TermQuery(newTerm("owner","jake")));
hits=searcher.search(query,jakeFilter);//所有owner域为jake的且kword域含info的文档
}
5、QueryFilter的替代方案
public void testFilter throws Exception{
TermQuery categoryQuery=newTermQuery(new Term("category","/philosophy/eastern"));
BooleanQuery conQuery=newBooleanQuery();
conQuery.add(allBooks,true,false);
conQuery.add(categoryQuery,true,false);
Hitshits=searcher.search(con1uery);
}
6、缓存过滤器结果
对于某此不具有缓存功能的过滤器来说,将它们馐到CachingWrapperFilter中后,Lucene会自动对非缓存过滤器的结果进行缓存(没有被引用的条目会被垃圾收集器清理)。
使用同一个IndexReader实例是使用过滤器缓存的关键。当索引的改变需要体现在搜索过程中时,就需要丢弃原来创建的IndexSearcher实现和IndexReader实例,将它们重新实例化
public void testcachingWrappper() throwsException{
Date jan1=parseDate("2004 Jan 01");
Date dec31=parseDate("2004Dec31");
DateFilter datefilter=new DateFiler("modified",jan1,dec31);
cachingFilter=new CachingWrapperFilter(datefilter);
Hits hits=searcher.search(allBooks,cachingFilter);
}
7、其他非内置的过滤器,在SandBox工具包中提供
1)ChainedFilter组成复杂的过滤器链。
2)FilteredQuery可以对某个查询进行过滤,因为在BooleanQuery对象中,它可做为一个单独查询子句,在不表示查询子句时,它又跟普通的search(Query,Filter)方法所具备的功能是一样的