两个聚合的 Elasticsearch Common of Beingicsearch



我想找到顶级作者和顶级合著者聚合的常见文档计数,这些是索引中源的biblio数据字段中的字段。

我目前正在做的是:

1.计算前10位作者的汇总。(A,B,C,D....)。

2.计算前10名合著者(X,Y,Z,....)的聚合。

3.计算交叉点的文档计数,例如这些对之间的公共文档计数:

[(A,X), (B,Y)....]. <-----结果

我尝试了子存储桶聚合,但它给了我: [A:(前 10 名对应 A),B:(前 10 名对应 B).....]。

好的,所以从上面的评论继续作为答案,使其更易于阅读且没有字符限制。

评论

我认为您无法使用管道聚合来实现它。

我想在客户端处理的并不多。 只有 20 条记录(作者 10 条,合著者 10 条),这将是简单的聚合查询。

另一种选择是只在两个字段中获取前 10 名以及简单的 agg 查询。

但是,如果您真的需要在 ES 端将两个前 10 名相交,请使用脚本化指标聚合。 您可以在代码中放置逻辑

第一个选项非常简单:

GET index_name/_search
{
"size": 0, 
"aggs": {
"firstname_dupes": {
"terms": {
"field": "authorFullName.keyword",
"size": 10
}
},
"lastname_dupes": {
"terms": {
"field": "coauthorFullName.keyword",
"size": 10
}
}
}
}

然后你在客户端对结果进行交集。

第二个看起来像:

GET index_name/_search
{
"size": 0, 
"aggs": {
"name_dupes": {
"terms": {
"script": {
"source": "return [doc['authorFullName.keyword'].value,doc['coauthorFullName.keyword'].value]"
}
, "size": 10
}
}
}
}

但它并不是前 10 名作者和前 10 名合著者的交集。 这是所有人的交集,然后进入前 10 名。

第三个选项是编写脚本化指标聚合。没有时间花在算法方面(应该优化),但它可能看起来像这个。当然,Java技能会对你有所帮助。此外,请确保您了解脚本化指标聚合执行的所有阶段以及使用它时可能遇到的性能问题。

GET index_name/_search
{
"size": 0, 
"query" : {
"match_all" : {}
},
"aggs": {
"profit": {
"scripted_metric": {
"init_script" : "state.fnames = [:];state.lnames = [:];", 
"map_script" :
"""
def key = doc['authorFullName.keyword'];
def value = '';
if (key != null && key.value != null) {
value = state.fnames[key.value];
if(value==null) value = 0;
state.fnames[key.value] = value+1
}
key = doc['coauthorFullName.keyword'];
if (key != null && key.value != null) {
value = state.lnames[key.value];
if(value==null) value = 0;
state.lnames[key.value] = value+1
}
""",
"combine_script" : "return state",
"reduce_script" : 
"""
def intersection = [];
def f10_global = new HashSet();
def l10_global = new HashSet();
for (state in states) {
def f10_local = state.fnames.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).limit(10).map(e->e.getKey()).collect(Collectors.toList());
def l10_local = state.lnames.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).limit(10).map(e->e.getKey()).collect(Collectors.toList());
for(name in f10_local){f10_global.add(name);}
for(name in l10_local){l10_global.add(name);}
}
for(name in f10_global){
if(l10_global.contains(name)) intersection.add(name);
}
return intersection;
"""
}
}
}
}

请注意,此处的查询假定您对这些属性具有keyword。如果不是,只需将它们调整到您的情况。

更新

PS,刚刚注意到您提到您需要通用计数,而不是通用名称。 不知道是什么情况,但不是map(e->e.getKey())使用map(e->e.getValue().toString()).请参阅有关类似问题的其他答案

相关内容

  • 没有找到相关文章

最新更新