上周在使用范围搜索时又遇到问题 ,程序抛出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) ...{
return new RangeFilter("viewedcount", "0000000000",
"0000000100", true, true);
} else if (advancedSearchVO.getViewedRank() == 2) ...{
return new RangeFilter("viewedcount", "0000000100",
"0000001000", true, true);
} else if (advancedSearchVO.getViewedRank() == 3) ...{
return new RangeFilter("viewedcount", "0000001000",
"0000010000", true, true);
} else if (advancedSearchVO.getViewedRank() == 4) ...{
return new RangeFilter("viewedcount", "0000010000",
"0150000000", true, true);
}
}
if (advancedSearchVO.getViewedRank() == 1) ...{
return new RangeFilter("viewedcount", "0000000000",
"0000000100", true, true);
} else if (advancedSearchVO.getViewedRank() == 2) ...{
return new RangeFilter("viewedcount", "0000000100",
"0000001000", true, true);
} else if (advancedSearchVO.getViewedRank() == 3) ...{
return new RangeFilter("viewedcount", "0000001000",
"0000010000", true, true);
} else if (advancedSearchVO.getViewedRank() == 4) ...{
return new RangeFilter("viewedcount", "0000010000",
"0150000000", true, true);
}
}
再使用
IndexSearch.search(Query query,Filter filter),
个人比较喜欢最后一种方案,第一种有潜在的危险,第二种又有些脆弱(索引受应用影响大,不稳定),最后一种比较折中一点
前面所说的咚咚确实解决了一个filter的问题,如果你有多个范围搜索,也就是说通常你需要多个filter, filter如何嵌套?
首先建立一个filterlist
public
List buildFilterList(ISearchVO searchVO)
...
{
List filterList = new ArrayList();
..........................
if (advancedSearchVO.getViewedRank() > 0) ...{
if (advancedSearchVO.getViewedRank() == 1) ...{
filterList.add(new RangeFilter("viewedcount", "0000000000",
"0000000100", true, true));
} else if (advancedSearchVO.getViewedRank() == 2) ...{
filterList.add(new RangeFilter("viewedcount", "0000000100",
"0000001000", true, true));
} else if (advancedSearchVO.getViewedRank() == 3) ...{
filterList.add(new RangeFilter("viewedcount", "0000001000",
"0000010000", true, true));
} else if (advancedSearchVO.getViewedRank() == 4) ...{
filterList.add(new RangeFilter("viewedcount", "0000010000",
"0150000000", true, true));
}
}
...........................
return filterList;
}
List filterList = new ArrayList();
..........................
if (advancedSearchVO.getViewedRank() > 0) ...{
if (advancedSearchVO.getViewedRank() == 1) ...{
filterList.add(new RangeFilter("viewedcount", "0000000000",
"0000000100", true, true));
} else if (advancedSearchVO.getViewedRank() == 2) ...{
filterList.add(new RangeFilter("viewedcount", "0000000100",
"0000001000", true, true));
} else if (advancedSearchVO.getViewedRank() == 3) ...{
filterList.add(new RangeFilter("viewedcount", "0000001000",
"0000010000", true, true));
} else if (advancedSearchVO.getViewedRank() == 4) ...{
filterList.add(new RangeFilter("viewedcount", "0000010000",
"0150000000", true, true));
}
}
...........................
return filterList;
}
然后嵌套
public
Query buildFilteredQuery(List filterlist, Query query)
...
{
if (filterlist == null || filterlist.size() < 1) ...{
return query;
}
FilteredQuery filteredQuery = null;
for (int i = 0; i < filterlist.size(); i++) ...{
if (i == 0) ...{
filteredQuery = new FilteredQuery(query, (Filter) filterlist
.get(i));
} else ...{
filteredQuery = new FilteredQuery(filteredQuery,
(Filter) filterlist.get(i));
}
}
return filteredQuery;
}
if (filterlist == null || filterlist.size() < 1) ...{
return query;
}
FilteredQuery filteredQuery = null;
for (int i = 0; i < filterlist.size(); i++) ...{
if (i == 0) ...{
filteredQuery = new FilteredQuery(query, (Filter) filterlist
.get(i));
} else ...{
filteredQuery = new FilteredQuery(filteredQuery,
(Filter) filterlist.get(i));
}
}
return filteredQuery;
}
最后
query
=
buildQuery();
。。。。
query = buildFilteredQuery( this .buildFilterList(searchVO), query);
Hits hits = searcher.search(query, sort);
。。。。
。。。。
query = buildFilteredQuery( this .buildFilterList(searchVO), query);
Hits hits = searcher.search(query, sort);
。。。。