上周在使用范围搜索时又遇到问题,程序抛出TooManyClauses exception。后来才发现lucene将范围搜索转化为精确匹配,每个匹配对应一个clause,所以如果你的范围如果包含超过1024个索引值,程序就会抛错
由此想到3种方案
1)
既然lucene限制了clause的个数,那么可以通过
BooleanQuery.setMaxClauseCount(Integer.MAX_VALUE)
改变限制,这个可以解决问题,但有隐患,如果某个范围的索引特别多,内存会有爆掉的危险。
2)根据应用修改索引
比如你有一个范围是视频观看数量(viewedcount) 1000-10000,那么你可以将这个范围内的所有的视频定为一个值(viewedcountlevel),也就是应用的每个搜索范围定为一个值,一个应用了不起10个范围,那么对范围档次建索引,到时候搜的根据 viewedcountlevel而不是viewedcount,将范围搜索以应用的角度转化为精确搜
3)使用filter
比如产生一个RangeFilter
if
(advancedSearchVO.getViewedRank()
>
0
)
...
{

if(advancedSearchVO.getViewedRank()==1)...{
returnnewRangeFilter("viewedcount","0000000000",
"0000000100",true,true);

}elseif(advancedSearchVO.getViewedRank()==2)...{
returnnewRangeFilter("viewedcount","0000000100",
"0000001000",true,true);

}elseif(advancedSearchVO.getViewedRank()==3)...{
returnnewRangeFilter("viewedcount","0000001000",
"0000010000",true,true);

}elseif(advancedSearchVO.getViewedRank()==4)...{
returnnewRangeFilter("viewedcount","0000010000",
"0150000000",true,true);
}
}

再使用
IndexSearch.search(Queryquery,Filterfilter),
个人比较喜欢最后一种方案,第一种有潜在的危险,第二种又有些脆弱(索引受应用影响大,不稳定),最后一种比较折中一点
前面所说的咚咚确实解决了一个filter的问题,如果你有多个范围搜索,也就是说通常你需要多个filter, filter如何嵌套?
首先建立一个filterlist
public
ListbuildFilterList(ISearchVOsearchVO)
...
{
ListfilterList=newArrayList();

..........................

if(advancedSearchVO.getViewedRank()>0)...{

if(advancedSearchVO.getViewedRank()==1)...{
filterList.add(newRangeFilter("viewedcount","0000000000",
"0000000100",true,true));

}elseif(advancedSearchVO.getViewedRank()==2)...{
filterList.add(newRangeFilter("viewedcount","0000000100",
"0000001000",true,true));

}elseif(advancedSearchVO.getViewedRank()==3)...{
filterList.add(newRangeFilter("viewedcount","0000001000",
"0000010000",true,true));

}elseif(advancedSearchVO.getViewedRank()==4)...{
filterList.add(newRangeFilter("viewedcount","0000010000",
"0150000000",true,true));
}
}

...........................
returnfilterList;
}
然后嵌套
public
QuerybuildFilteredQuery(Listfilterlist,Queryquery)
...
{


if(filterlist==null||filterlist.size()<1)...{
returnquery;
}

FilteredQueryfilteredQuery=null;

for(inti=0;i<filterlist.size();i++)...{

if(i==0)...{
filteredQuery=newFilteredQuery(query,(Filter)filterlist
.get(i));

}else...{

filteredQuery=newFilteredQuery(filteredQuery,
(Filter)filterlist.get(i));
}
}

returnfilteredQuery;

}
最后
query
=
buildQuery();
。。。。
query
=
buildFilteredQuery(
this
.buildFilterList(searchVO),query);
Hitshits
=
searcher.search(query,sort);
。。。。