我有一个用例,我需要显示来自组和排序聚合的前10个和后10个结果。我尝试使用$limit
,但这不会让下一个聚合器处理完整的数据。
db.collection.aggregate([groupAggregator, sortAggregator, { $limit: 10 }, /*only 10 records available*/]
如何在管道中间对整个集合执行聚合?我正在使用MongoDB 3.2.9
。如果那是不可能的话,UNION有两种聚合方式,第一种是top 10 (ASC SORTED)
,第二种是last 10 (DESC SORTED)
,
如果没有用于群组聚合,我会使用db.collection.find({}).sort().filter()
策略,但该小组需要完成。
从组聚合中获取的数据
{_id: "", ..., avg_count: 10}
{_id: "", ..., avg_count: 1}
{_id: "", ..., avg_count: 2}
{_id: "", ..., avg_count: 5}
{_id: "", ..., avg_count: 8}
{_id: "", ..., avg_count: 3}
{_id: "", ..., avg_count: 4}
{_id: "", ..., avg_count: 6}
{_id: "", ..., avg_count: 7}
{_id: "", ..., avg_count: 9}
从排序聚合
获得的数据{_id: "", ..., avg_count: 1}
{_id: "", ..., avg_count: 2}
{_id: "", ..., avg_count: 3}
{_id: "", ..., avg_count: 4}
{_id: "", ..., avg_count: 5}
{_id: "", ..., avg_count: 6}
{_id: "", ..., avg_count: 7}
{_id: "", ..., avg_count: 8}
{_id: "", ..., avg_count: 9}
{_id: "", ..., avg_count: 10}
期望的输出:
FETCH FIRST 2和最后2个文件
{_id: "", ..., avg_count: 1}
{_id: "", ..., avg_count: 2}
{_id: "", ..., avg_count: 9}
{_id: "", ..., avg_count: 10}
注意:以上只是一个示例数据,实际数据没有确切的序列号。
答案 0 :(得分:2)
如果理解正确,这是获得该行为的一种方式:
db.collection.aggregate([{
$sort: { "your_sort_field": 1 } // sort the data
}, {
$group: {
_id: null, // group everything into one single bucket
docs: { $push: "$$ROOT" } // push all documents into an array (this will be massive for huge collections...)
}
}, {
$project: {
"docsTop10": { $slice: [ "$docs", 10 ] }, // take the first 10 elements from the ASC sorted array
"docsBottom10": { $reverseArray: { $slice: [ "$docs", -10 ] } } // take the last 10 elements from the array but reverse their order
}
}])
如果您希望将所有内容都放在一个属性中,则可以在最后阶段使用$concatArrays:
$project: {
"result": { $concatArrays: [ { $slice: [ "$docs", 10 ] }, { $reverseArray: { $slice: [ "$docs", -10 ] } } ] }
}
不幸的是,你的MongoDB版本还没有$replaceRoot,否则你可以更好地平整结果。
此外,由于$reverseArray似乎在v3.2中也不可用,因此您可以在{{3}之后再删除该运算符$unwind和$sort。阶段:
{
$project: {
_id: 0,
"result": { $concatArrays: [ { $slice: [ "$docs", 10 ] }, { $slice: [ "$docs", -10 ] } ] }
}
}, {
$unwind: "$result"
}, {
$sort: { "result.your_sort_field": 1 } // sort the data
}
另一种选择是使用$project(仅从v3.4开始),这肯定会更快,因为MongoDB能够很好地优化排序/限制组合:
db.collection.aggregate([{
$facet: { // start two separate pipeline
"docsTop10": [
{ $sort: { "your_sort_field": 1 } }, // sort ASC
{ $limit: 10 } // take top 10
],
"docsBottom10": [
{ $sort: { "your_sort_field": -1 } }, // sort DESC
{ $limit: 10 } // take top 10
]
}
}])