【问题标题】:Bluebird promise concurrency in mongo db collection migrate operationsBluebird 在 mongo db 集合迁移操作中承诺并发
【发布时间】:2019-07-25 12:36:20
【问题描述】:

我正在编写一个脚本,我需要从 mongodb 集合中获取数据,通过一些重命名和映射对其进行处理,然后将数据放到其他集合中。我在 expressjs 中使用这个脚本和用于 nodejs 的 mongodb-native 客户端。

这是我的所有运行函数的脚本

const syncCustomerWithCustomerv1 = function(params){
    utils.connectDB().then((client) => {
        Promise.map(aggregateDocumentsv1(client, params), function(cursor){
            Promise.map(getCustomerDatav1(cursor), function(customer){

                var hashedMap = makeHashedObjectv1(customer);
                makeDatav1(client, customer, hashedMap).then((response)=> {
                    console.log("success");
                }).catch((error) => {
                    console.log(error);
                    reject(error);
                })
            }, {concurrency: 500});
        }, {concurrency: 500}).then((reponse) => {  
            console.log("data inserted");
        })
    }).catch((error) => {
        console.log(error);
    });
}

现在在名为 syncCustomerWithCustomerv1 的函数中,我可以将旧集合中的数据提取到新集合中,但我认为不会有任何并发​​请求。在上述操作运行时,我无法点击 api,所以当操作运行时,它不允许其他请求一起运行。

  • 在 Promise.map(aggregateDocumentsv1) 中,我正在获取游标列表。 listOfCursor 数组中的每个元素都有一个游标,查询时会产生 500 条记录。

  • 我希望它获取每个光标并将其分配给下一个 Promise.map(getCustomerDatav1(cursor)),现在这会产生我以前的 mongo 集合中的每个客户,我们可以在我们得到的对象,然后将数据插入到新的集合中。

如果有人遇到问题并知道如何使其更好地并发,以便我可以运行此脚本并且我的 API 也不会出现任何停机时间。

【问题讨论】:

  • 你到底想达到什么目的?? bluebird 中的并发性对并发执行的操作设置了限制,即在任何时间段内最多有 500 个解析器函数实例正在运行。如果您不指定此选项,则该函数将同时在您的所有文档上调用。
  • 我认为你有这个错误的方式。 Promise.map(arrayOfItems, e => functionReturningPromise(e)) 基本上是Promise.all(arrayOfItems.map(e => functionReturningPromise(e)) 的“帮手”。您同时提供了“承诺数组”并尝试“迭代”结果,但这不是 Promise.map() 的函数参数所做的。
  • 嘿@ilLunn NeilLunn,所以应该有第二个 Promise.map 需要重写为 Promise.any。
  • 如果你看一下我的用法示例,first 参数基本上是一个数组,second 是基本上是Array.prototype.map() 的函数。最重要的是,这意味着返回一个数据数组,而您忽略了该返回。建议您宁愿解释您正在尝试做的事情,因为代码有点混乱,并且您实际上是在包装已经返回 Promise 和新 Promise 的方法。尝试了解问题中的点应该发生的事情的逻辑。
  • 嗯。我可以在这里尝试一个简化的解释吗?看来您实际上是 1. 从一个集合中读取客户名称和电子邮件。 2. 执行“查找或创建”以将相同的名称和电子邮件数据写入另一个集合。问题是“这是在同一个数据库服务器上,还是在不同的机器上?目标集合(“查找或创建”一个)实际上是否已经预先存在其中的数据,或者它可以完全被覆盖”。这是我的基本解释,实际上是我想让你解释的。没有冒犯,但试图解释当前的代码没什么意义。

标签: node.js mongodb promise bluebird


【解决方案1】:

我不了解 MongoDB,但是您的承诺代码存在一些问题:

  • 对于能够等待异步回调结果的任何函数(无论是 Promise.mapthen),该回调必须 return 等待等待的承诺
  • 您正在执行 500 个并发操作,其中每个操作执行 500 个并发操作。那是250000的总并发因子!你可能想减少一点。

function syncCustomerWithCustomerv1(params){
    utils.connectDB().then(client => {
        return Promise.map(aggregateDocumentsv1(client, params), cursor => {
//      ^^^^^^
            return Promise.map(getCustomerDatav1(cursor), customer => {
//          ^^^^^^
                var hashedMap = makeHashedObjectv1(customer);
                return makeDatav1(client, customer, hashedMap).then(response => {
//              ^^^^^^
                    console.log("success");
                }, error => {
                    console.log(error);
                });
            }, {concurrency: 500});
        }, {concurrency: 500})
    }).then(reponse => {  
        console.log("data inserted");
    }, error => {
        console.log(error);
    });
}

【讨论】:

    猜你喜欢
    • 2016-07-27
    • 1970-01-01
    • 1970-01-01
    • 2017-08-06
    • 1970-01-01
    • 2018-02-01
    • 2015-10-23
    • 2013-10-26
    • 2017-04-08
    相关资源
    最近更新 更多