如何从带有 MongoDB 的游标中查找下 N 个元素,没有 _id 并且在已排序的游标上

Pat*_*aba 3 javascript mongodb mongodb-query typescript

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

{
  "firstName": "Hulda",
  "lastName": "Lamb",
},
{
  "firstName": "Austin",
  "lastName": "Todd",
},
{
  "firstName": "John",
  "lastName": "Doe",
}
Run Code Online (Sandbox Code Playgroud)

我的目标是在列表按字母顺序排列时获得,比方说,Austin 之后的下一个人。所以我想得到 firstName = Hulda 的人。我们可以假设我知道 Austin 的_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();
Run Code Online (Sandbox Code Playgroud)

一些澄清:

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

mic*_*ckl 5

每个 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"
        }
    }
])
Run Code Online (Sandbox Code Playgroud)

蒙戈游乐场

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