首页 > 解决方案 > 如何从带有 MongoDB 的游标中查找下一个 N 元素,没有 _id 并且在排序游标上

问题描述

假设我在 MongoDB 中有三个人员文档,以随机顺序插入。

{
  "firstName": "Hulda",
  "lastName": "Lamb",
},
{
  "firstName": "Austin",
  "lastName": "Todd",
},
{
  "firstName": "John",
  "lastName": "Doe",
}

我的目标是在列表按字母顺序排列时获得奥斯汀之后的下一个人。所以我想得到名字 = Hulda 的人。我们可以假设我知道奥斯汀的_id. 我的第一次尝试是依赖于增量的事实_id,但它不会起作用,因为可以在数据库中以任何顺序添加人员。Hulda 的_id字段值小于 Austin 的值。我不能做类似的事情{_id: {$gt: <Austin's _id here>}}; 而且我还需要限制返回元素的数量,所以 N 是一个动态值。

这是我现在拥有的代码,但正如我所提到的,ID 技巧不起作用。

let cursor: any = this.db.collection(collectionName).find({_id: {$gt: 
cursor = cursor.sort({firstName: 1});
cursor = cursor.limit(limit);

return cursor.toArray();

一些澄清:

  1. startId是对象的有效的现有 _id
  2. limit是一个持有正整数值的变量
  3. 排序和限制按预期工作,只是下一个元素的选择是错误的,所以{_id: {$gt: startId}};选择混乱。

标签: javascriptmongodbtypescriptmongodb-query

解决方案


每个 MongoDB 的聚合框架操作的上下文都被限制在一个文档中。SQL 中没有像窗口函数这样的机制。您唯一的方法是使用$group获取包含所有文档的数组,然后获取Austin能够应用$slice的索引:

db.collection.aggregate([
    {
        $sort: { firstName: 1 }
    },
    {
        $group: {
            _id: null,
            docs: { $push: "$$ROOT" }
        }
    },
    {
        $project: {
            nextNPeople: {
                $slice: [ "$docs", { $add: [ { $indexOfArray: [ "$docs.firstName", "Austin" ] }, 1 ] }, 1 ]
            }
        }
    },
    { $unwind: "$nextNPeople" },
    {
        $replaceRoot: {
            newRoot: "$nextNPeople"
        }
    }
])

蒙戈游乐场

根据您的数据大小 / MongoDB 性能,上述解决方案可能会或可能不会被接受 - 由您决定是否要在生产中部署此类代码,因为$group操作可能非常繁重。


推荐阅读