node.js - Mongo 聚合查询在服务器上花费的时间太长

标签 node.js mongodb aggregation-framework

我正在尝试在 mongo 中使用聚合框架来获取一些数据统计信息。我正在使用的查询,当在本地运行时几乎不需要一分钟,但是当我在服务器上运行相同的查询时它没有给出响应并且在等待太久之后,我不得不取消它,任何人都可以请建议为什么是这发生了。

var orderIds = db.delivery.find({"status":"DELIVERED"}).map(function(o) {
    return o.order 
}); 

var userIds =  db.order.aggregate([{
    $match : { _id : { $in : orderIds } }
}, {
    $group: { _id : "$customer" }
}]).map(function(u) { return u._id });

var userstats = db.order.aggregate([{
    $sort : { customer : 1, dateCreated : 1 }
}, {
    $match : { status : "DELIVERED", customer : {  $in : userIds } }
}, { 
    $group: {
        _id : "$customer", orders : { $sum : 1 }, 
        firstOrderDate : { $first : "$dateCreated" },
        lastOrderDate : { $last : "$dateCreated" }
    }
}]);

userstats.forEach(function(x) { 
    db.user.update({ _id : x._id }, {
        $set : { 
            totalOrders : x.orders,
            firstOrderDate : x.firstOrderDate,
            lastOrderDate : x.lastOrderDate
        }
    })
})

我不确定,但它在服务器上不应该更快吗? ,但它无法提供输出。

最佳答案

要加快流程,您可以通过多种方式重构您的操作。 第一个是消除不必要的管道操作,如 $sort 运算符可以替换为 $max $min $group 中的运算符 管道。

其次,使用 bulk() API 这将提高更新操作的性能,尤其是在处理大型集合时,因为它们会将操作分批发送到服务器(例如,批量大小为 500),这与将每个请求发送到服务器(如您当前正在 forEach() 循环中执行更新语句。

考虑以下重构操作:

var orderIds = db.delivery.find({"status": "DELIVERED"}).map(function(d){return d.order;}),
    counter = 0,
    bulk = db.user.initializeUnorderedBulkOp();

var userstatsCursor = db.orders.aggregate([
    { "$match": { "_id": { "$in": orderIds } } },
    { 
        "$group": { 
            "_id": "$customer", 
            "orders": { "$sum": 1 },
            "firstOrderDate": { "$min": "$dateCreated" },
            "lastOrderDate":{ "$max": "$dateCreated" } } 
        } 
    }
]);

userstatsCursor.forEach(function (x){
    bulk.find({ "_id": x._id }).updateOne({ 
        "$set": { 
            "totalOrders": x.orders,
            "firstOrderDate": x.firstOrderDate,
            "lastOrderDate": x.lastOrderDate
        }
    });

    counter++;
    if (counter % 500 == 0) {
        bulk.execute(); // Execute per 500 operations and 
        // re-initialize every 500 update statements
        bulk = db.user.initializeUnorderedBulkOp();
    }
});

// Clean up remaining operations in queue
if (counter % 500 != 0) { bulk.execute(); }

关于node.js - Mongo 聚合查询在服务器上花费的时间太长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35367083/

相关文章:

node.js - 使用进程文件将 --node-args --inspect 传递给 pm2

node.js - MongoDB:动态计数

node.js - 如何使用时间戳作为mongodb和nodejs中的字段按天对记录进行分组

node.js - Node 中的角色和锁定端点

javascript - 错误 'getaddrinfo EAI_AGAIN' 的原因是什么?

c# - 使用 C# 驱动程序更新/删除 mongodb 中的子文档

node.js - 从 mongodb 游标流式传输到 node.js 中的 Express 响应

c# - MongoDB LinQ "Select"方法真的只会检索字段的子集吗?

javascript - 将 mongo db 查询减少为纯数组

javascript - TypeError : app. get 不是函数