我有一个Elasticsearch书籍数据库:
{
"id": 1,
"name": "Animal Farm"
},
{
"id": 2,
"name": "Brave New World"
},
{
"id": 3,
"name": "Nineteen Eighty-Four"
},
{
"id": 4,
"name": "Animal Farm"
},
{
"id": 5,
"name": "We"
}
如您所见,id
1
和4
的图书的冲突书名为“动物农场”。但是,它们是不同的书籍。一个是George Orwell,另一个是农场动物。
我想知道书名经常发生冲突的频率。对于上面的示例,预期结果为:
{
"conflicts": [
{
"num_of_books": 2,
"count": "1"
},
{
"num_of_books": 1,
"count": "3"
}
]
}
num_of_books
2
的条目是“动物农场”的冲突,它发生一次(因此count
是1
)。其他3本书的名称各有不同,因此它们会显示在num_of_books
1
和count
3
的条目中。我不需要书籍的名称。只有重要的事情。
我知道SQL有“子查询”来执行此操作:
SELECT num_of_books, COUNT(*) AS _count
FROM (
SELECT COUNT(*) AS num_of_books
FROM books
GROUP BY name
)
GROUP BY num_of_books;
我阅读了Nested Aggregation和Sub-Aggregations的文章,但没有看到实现目标的可能性。
任何评论都会有所帮助,谢谢!
答案 0 :(得分:0)
据我所知,ES中尚无法在聚合上运行聚合。我知道一些关于允许在存储桶聚合结果上应用额外逻辑的未决问题,但它们仍在讨论和争论中。
在您的情况下,您可以使用terms
聚合来逃避内部SQL查询,以便使用min_doc_count: 2
获取所有冲突书籍的名称。
{
"size": 0,
"aggs": {
"books": {
"terms": {
"field": "name",
"min_doc_count": 2
}
}
}
}
然后,您可以解析客户端上的存储桶,并根据其计数将它们重新装入新的num_of_books
存储桶。例如,使用head插件,您可以在Transform部分
var num_of_books = {};
root.aggregations.books.buckets.forEach(function(b) {
num_of_books[b.doc_count] = (num_of_books[b.doc_count] || 0) + 1;
});
return num_of_books;
num_of_books
将包含以下内容:
{
"2": 1,
"1": 3
}