首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从MongoDB集合中获取第N条和最后N条记录

从MongoDB集合中获取第N条和最后N条记录
EN

Stack Overflow用户
提问于 2017-12-14 20:50:12
回答 1查看 2.8K关注 0票数 0

我有一个用例,在这个用例中,我需要显示一个组的前10名和最后10名的结果,并对聚合进行排序。我尝试使用$limit,但这不会让下一个聚合器处理完整的数据。

代码语言:javascript
运行
复制
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()策略,但是这个组需要完成。

从组聚合中获得的数据

代码语言:javascript
运行
复制
{_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}

从排序聚合中获得的数据

代码语言:javascript
运行
复制
{_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份文件

代码语言:javascript
运行
复制
{_id: "", ..., avg_count: 1}
{_id: "", ..., avg_count: 2}
{_id: "", ..., avg_count: 9}
{_id: "", ..., avg_count: 10}

注意:上面的只是一个样本数据,实际数据没有确切的序列号。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-12-14 21:07:47

如果你的理解是正确的,那么有一种方法可以让你理解你的行为:

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
$project: {
    "result": { $concatArrays: [ { $slice: [ "$docs", 10 ] }, { $reverseArray: { $slice: [ "$docs", -10 ] } } ] }
}

不幸的是,在您的$replaceRoot版本中还没有MongoDB,否则您可以更好地平平结果。

此外,由于$reverseArray似乎在第3.2版中不可用,所以您只需在$project阶段之后再删除该操作符、$unwind$sort一次:

代码语言:javascript
运行
复制
{
    $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能够很好地优化排序/限制组合:

代码语言:javascript
运行
复制
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
        ]
    }
}])
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47821821

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档