【问题标题】:MongoDB aggregation lookup with pagination is working slow in huge amount of data带有分页的 MongoDB 聚合查找在大量数据中运行缓慢
【发布时间】:2019-11-13 17:11:31
【问题描述】:

我在 MongoDB 中有一个包含超过 150 000 个文档的集合。我在 Node.js 中为 MongoDB 使用 Mongoose ODM v5.4.2。在检索数据时,我使用带有 $skip 和 $limit 的聚合查找进行分页。我的代码运行良好,但在 100k 个文档之后检索数据需要 10-15 秒。但是在 $skip 和 $limit 的帮助下,我一次只显示 100 条记录。我已经为foreignField 创建了索引。但它仍然变慢了。

campaignTransactionsModel.aggregate([{
                    $match: {
                campaignId: new importModule.objectId(campaignData._id)
            }
                },
                {
                    $lookup: {
                        from: userDB,
                        localField: "userId",
                        foreignField: "_id",
                        as: "user"
                    },
                },
                {
                    $lookup: {
                        from: 'campaignterminalmodels',
                        localField: "terminalId",
                        foreignField: "_id",
                        as: "terminal"
                    },
                },
                {
                    '$facet': {
                        edges: [{
                                $sort: {
                                    [sortBy]: order
                                }
                            },
                            { $skip: skipValue },
                            { $limit: viewBy },
                        ]
                    }
                }
            ]).allowDiskUse(true).exec(function(err, docs) {
                console.log(docs);
            });

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    查询需要更长的时间,因为服务器从输入结果的开头(跳过阶段之前)扫描以跳过给定数量的文档并设置新结果。

    来自官方 MongoDB 文档:

    cursor.skip() 方法要求服务器从 开始输入结果集之前开始返回结果。 随着偏移量的增加,cursor.skip() 会变慢。

    您可以使用range 查询来模拟与.skip()skip stage(aggregation) 类似的结果

    使用范围查询

    范围查询可以使用索引来避免扫描不需要的文档, 随着偏移量的增长,通常会产生更好的性能 使用 cursor.skip() 进行分页。

    降序

    使用此过程通过范围查询实现分页:

    • 选择一个字段,例如 _id,它通常会以一致的方式更改 随时间变化的方向,并具有唯一索引以防止重复 价值观
    • 查询字段小于起始值的文档 使用 $ltcursor.sort() 运算符,以及
    • 为下一个查询存储上次查看的字段值。

    递增顺序 - 查询字段小于起始值的文档 使用$gtcursor.sort() 运算符,以及

    假设您获得的最后一个文档具有 _id : objectid1,那么您可以查询具有_id : {$lt : objectid1} 的文档以按降序获取文档。对于递增顺序,您可以查询具有_id : {$gt : objectid1}的文档

    阅读Range queries 上的官方文档了解更多信息。

    【讨论】:

      猜你喜欢
      • 2020-10-10
      • 2017-03-17
      • 2011-11-05
      • 2020-11-23
      • 2022-01-03
      • 2018-07-09
      • 1970-01-01
      • 2023-04-08
      相关资源
      最近更新 更多