解决lucene范围搜索中的TooManyClauses exception

上周在使用范围搜索时又遇到问题,程序抛出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);
。。。。

你可能感兴趣的:(Lucene)