最近在优化搜索服务,以前的搜索服务十分简单,现在需要增加查询结果分组统计的功能,以提高用户体验。
g了一番,有以下几个主要的实现方式:
1、利用search中的collect,自己实现一个collect输出分组统计结果;
2、一个开源的lucene插件bobo browser
3、lucnen3.2后有个grouping模块
最后我选择了grouping这个模块来实现
grouping模块有2种方法实现,2次遍历法和1次遍历法。1次遍历法是在lucene3.3之后才开始提供。
1次遍历法效率很高,但是需要在索引时添加特殊的标志:
To use the single-pass BlockGroupingCollector
, first, at indexing time, you must ensure all docs in each group are added as a block, and you have some way to find the last document of each group. One simple way to do this is to add a marker binary field:
网站访问量目前还很小,又不想重新建索引,于是还是采用了2次遍历法。2次遍历的第一次遍历是把分组拿出来,如果您只需要分组,不需要各个分组的数量,可以一次遍历即可。第二次遍历是把各个分组的搜索结果拿出来,当然也就能知道各个分组的数量。
2次遍历法由于需要经过2次搜索效率较低,因此引入了一个cache机制,CachingCollector。这样在第二次遍历是就可以直接读内存了。
代码片段如下:
public Map<String, Integer> groupBy(Query query, String field, int topCount) {
Map<String, Integer> map = new HashMap<String, Integer>();
long begin = System.currentTimeMillis();
int topNGroups = topCount;
int groupOffset = 0;
int maxDocsPerGroup = 100;
int withinGroupOffset = 0;
try {
TermFirstPassGroupingCollector c1 = new TermFirstPassGroupingCollector(field, Sort.RELEVANCE, topNGroups);
boolean cacheScores = true;
double maxCacheRAMMB = 4.0;
CachingCollector cachedCollector = CachingCollector.create(c1, cacheScores, maxCacheRAMMB);
indexSearcher.search(query, cachedCollector);
Collection<SearchGroup<String>> topGroups = c1.getTopGroups(groupOffset, true);
if (topGroups == null) {
return null;
}
TermSecondPassGroupingCollector c2 = new TermSecondPassGroupingCollector(field, topGroups, Sort.RELEVANCE, Sort.RELEVANCE, maxDocsPerGroup, true, true, true);
if (cachedCollector.isCached()) {
// Cache fit within maxCacheRAMMB, so we can replay it:
cachedCollector.replay(c2);
} else {
// Cache was too large; must re-execute query:
indexSearcher.search(query, c2);
}
TopGroups<String> tg = c2.getTopGroups(withinGroupOffset);
GroupDocs<String>[] gds = tg.groups;
for(GroupDocs<String> gd : gds) {
map.put(gd.groupValue, gd.totalHits);
}
} catch (IOException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("group by time :" + (end - begin) + "ms");
return map;
}
几个参数说明:
-
groupField
: 分组域
-
groupSort
: 分组排序
-
topNGroups
: 最大分组数
-
groupOffset
: 分组分页用
-
withinGroupSort
: 组内结果排序
-
maxDocsPerGroup
: 每个分组的最多结果数
-
withinGroupOffset
: 组内分页用
分享到:
相关推荐
Lucene多个group by字段实现,字段个数动态。
一步一步跟我学习lucene是对近期做lucene索引的总结,
lucene.net,搜索引擎,锤子搜索引擎分组统计
NULL 博文链接:https://iamyida.iteye.com/blog/2202651
lucene 通过FieldCache 实现分组统计 附完整代码
Lucene.net分组
我的博客专栏http://blog.csdn.net/wuyinggui10000/article/category/3173543,希望大家关注
lucene-grouping-3.5.0.jar分组统计+分类统计插件 分组统计+分类统计
lucene实例lucene实例lucene实例lucene实例lucene实例lucene实例lucene实例lucene实例lucene实例
文件包含了lucene的创建、删除、修改、组合条件查询、类似mysql中like、in、or、以及时间范围条件查询
用到的工具 jsoup+spring+struct+DButil+mysql+lucene 可以配置采集网站的图片,包含分组统计,相同数据合并功能,主要是给群内成员来个demo,让大家有个学习的demo 小试牛刀、临时写的,莫吐槽 需要用到mysql...
lucene,lucene教程,lucene讲解。 为了对文档进行索引,Lucene 提供了五个基础的类 public class IndexWriter org.apache.lucene.index.IndexWriter public abstract class Directory org.apache.lucene.store....
lucene3.0 lucene3.0 lucene3.0 lucene3.0 lucene3.0
lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习lucene学习...
NULL 博文链接:https://zm603380946.iteye.com/blog/1827318
Lucene3.0特性Lucene3.0特性
lucene学习教程lucene讲义 叫你用lucene算法
lucene
lucene3源码分析
lucene