我有一个用例,在这个用例中,我需要显示一个组的前10名和最后10名的结果,并对聚合进行排序。我尝试使用$limit
,但这不会让下一个聚合器处理完整的数据。
db.collection.aggregate([groupAggregator, sortAggregator, { $limit: 10 }, /*only 10 records available*/]
如何对管道中间的整个集合执行聚合?我正在使用MongoDB 3.2.9
。如果这是不可能的话,有没有办法将两个聚合结合起来,第一个是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}
期望输出:
获取前2份和最后2份文件
{_id: "", ..., avg_count: 1}
{_id: "", ..., avg_count: 2}
{_id: "", ..., avg_count: 9}
{_id: "", ..., avg_count: 10}
注意:上面的只是一个样本数据,实际数据没有确切的序列号。
发布于 2017-12-14 21:07:47
如果你的理解是正确的,那么有一种方法可以让你理解你的行为:
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 ] } } ] }
}
不幸的是,在您的$replaceRoot版本中还没有MongoDB,否则您可以更好地平平结果。
此外,由于$reverseArray似乎在第3.2版中不可用,所以您只需在$project阶段之后再删除该操作符、$unwind和$sort一次:
{
$project: {
_id: 0,
"result": { $concatArrays: [ { $slice: [ "$docs", 10 ] }, { $slice: [ "$docs", -10 ] } ] }
}
}, {
$unwind: "$result"
}, {
$sort: { "result.your_sort_field": 1 } // sort the data
}
另一种选择是使用$facet (仅从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
]
}
}])
https://stackoverflow.com/questions/47821821
复制相似问题