mongodb 分页的聚合跳过限制计数

zah*_*med 2 pagination mongodb mongodb-query

我想对这个聚合数据(与集合 2 和集合 3 匹配并投影的所有文档)应用分页。我尝试了多个查询,我通过了 25 个限制,但它只会得到 20 个文档,在此查询中需要更改以进行分页

var pipeline = [{
        $match: query
    }, {
        $limit: limit
    }, {
        $skip: skip
    }, {
        $lookup: {
            from: "collection2",
            localField: "collection1Field",
            foreignField: "collection2Field",
            as: "combined1"
        }
    }, {
        "$unwind": "$combined1"
    }, {
        $lookup: {
            from: "collection3",
            localField: "collection1Field",
            foreignField: "collection3Field",
            as: "combined2"
        }
    }, {
        "$unwind": "$combined2"
    }, {
        $project: {
            "collection1Field1": 1,
            "collection1Field2": 1,
            "collection1Field3": 1,
            "collection2Field.field1": 1,
            "collection2Field.field2": 1,
            "collection3Field.field1": 1,
            "collection3Field.field2": 1,
        }
    }
];
Run Code Online (Sandbox Code Playgroud)

Dan*_*bin 7

我刚刚遇到了类似的问题。由于我跑了limit,我在“第 2 页”上没有得到任何结果skip

的文档$skip

跳过进入阶段的指定数量的文档,并将剩余的文档传递到管道中的下一个阶段。

的文档$limit

限制传递到管道中下一阶段的文档数量。

这意味着如果您在此limit之前运行,skip则限制返回的结果可能会被skip.

例如,如果limit是 50 和skip50(例如第 2 页),那么匹配将查找项目,将结果限制为 50,然后跳过 50,从而将 0 结果提供给之后的任何阶段。

我不建议在查询结束时运行$skip$limit查询,因为数据库将对大量数据执行管道操作,这些数据将在最后被跳过/限制。此外,可以使用的内存聚合数量有限制,如果超过限制(100MB - 见底部),它将以错误结束查询。如果超过此限制,则可以选择打开磁盘使用,但不依赖磁盘优化代码的好方法是在输入任何$lookup$unwind步骤之前跳过 + 限制结果。

该规则的一个例外是$sort它足够智能,可以使用$limitif$limit紧随其后$sort(文档):

当管道中的a$sort紧跟在 a 之前时$limit$sort 操作只会在执行过程中维护前n 个结果,其中n 是指定的限制,而 MongoDB 只需要在内存中存储n 个项目。当allowDiskUsetrue并且n项超过聚合内存限制时,此优化仍然适用。

从您的代码中,我会推荐以下内容(跳过然后限制):

var pipeline = [{
    $match: query
}, {
    $skip: skip
}, {
    $limit: limit
}, {
    $lookup: {
        from: "collection2",
        localField: "collection1Field",
        foreignField: "collection2Field",
        as: "combined1"
    }
}, {
    "$unwind": "$combined1"
}, {
    $lookup: {
        from: "collection3",
        localField: "collection1Field",
        foreignField: "collection3Field",
        as: "combined2"
    }
}, {
    "$unwind": "$combined2"
}, {
    $project: {
        "collection1Field1": 1,
        "collection1Field2": 1,
        "collection1Field3": 1,
        "collection2Field.field1": 1,
        "collection2Field.field2": 1,
        "collection3Field.field1": 1,
        "collection3Field.field2": 1,
    }
}];
Run Code Online (Sandbox Code Playgroud)

有关聚合管道限制的文档:

内存限制在 2.6 版中更改。

流水线阶段的 RAM 限制为 100 兆字节。如果阶段超过此限制,MongoDB 将产生错误。要允许处理大型数据集,请使用 allowDiskUse 选项启用聚合管道阶段以将数据写入临时文件。

在 3.4 版中更改。

$graphLookup阶段必须保持在100 MB的内存限制之内。如果allowDiskUse: trueaggregate()操作指定了, $graphLookup阶段将忽略该选项。如果有其他阶段的aggregate()操作,allowDiskUse: true选择在这些其他阶段的效果。