解决lucene范围搜索中的TooManyClauses exception

针对Lucene范围搜索引发TooManyClausesexception问题,探讨三种解决方案:调整BooleanQuery限制、按应用需求修改索引及使用RangeFilter进行过滤。通过具体代码示例展示了如何实现这些策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

publicListbuildFilterList(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;
}

然后嵌套

publicQuerybuildFilteredQuery(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);
。。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值