Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在mongoose/mongodb中扩展findOneAndUpdate以获得500万次更新?_Python_Node.js_Mongodb_Mongoose - Fatal编程技术网

Python 如何在mongoose/mongodb中扩展findOneAndUpdate以获得500万次更新?

Python 如何在mongoose/mongodb中扩展findOneAndUpdate以获得500万次更新?,python,node.js,mongodb,mongoose,Python,Node.js,Mongodb,Mongoose,我正在开发一个后端:nodejs、mongoose、mongodb、ironmq。还有另一个应用程序(python FTP服务器)用作数据源 系统或多或少是这样工作的: 用户将csv转储的数据(近300万条)上传到FTP服务器(这种情况定期发生,每24小时一次) FTP服务器解析数据,并同步批量(2000次)推送到IronMQ队列。我在这里进行批处理是为了优化内存 另一个应用程序(nodejs)不断轮询此队列中的数据,每10秒轮询100条消息(这是允许的最大数量),处理此数据,然后更新我的数据

我正在开发一个后端:nodejs、mongoose、mongodb、ironmq。还有另一个应用程序(python FTP服务器)用作数据源

系统或多或少是这样工作的:

  • 用户将csv转储的数据(近300万条)上传到FTP服务器(这种情况定期发生,每24小时一次)

  • FTP服务器解析数据,并同步批量(2000次)推送到IronMQ队列。我在这里进行批处理是为了优化内存

  • 另一个应用程序(nodejs)不断轮询此队列中的数据,每10秒轮询100条消息(这是允许的最大数量),处理此数据,然后更新我的数据库(对每条消息使用
    findOneAndUpdate
    )。我有5个这样的应用正在运行

现在,除了完成整个操作所需的时间外,这个设置没有任何明显的问题。解析后的数据完全推送到MQ几乎需要2个小时,但这不是什么大问题,因为它是成批完成的。实际问题来自“保存/更新到数据库”部分

平均而言,数据库中每小时更新20-24K个条目。但由于我有300万条条目,这需要24小时以上(这不起作用,因为FTP上的文件每24小时刷新一次,数据将用于在我的应用程序的其他部分执行某些操作)

我不确定接下来该怎么办,但我有几个问题要问

  • 我的上述方法是否可以被认为是最佳/有效的?或者有什么可以改进的
  • 如何通过db或更改设计来减少整个更新操作所需的时间
  • mongodb被认为适合这种情况,还是有更好的替代方案

如果你能在这方面提供一些帮助,那就太棒了。如果您需要更多信息,请务必告诉我。

您可以使用批量API方法优化更新,这些方法非常有效,因为它们允许您在单个请求(作为一个批处理)中向服务器发送多个更新操作。 请考虑以下示例,演示不同MangoDB版本的这种方法:

假设您的nodejs应用程序将消息数据轮询到列表中,对于支持MongoDB Server的Mongoose版本
>=4.3.0
,您可以使用更新集合,如下所示:

var bulkUpdateCallback = function(err, r){
        console.log(r.matchedCount);
        console.log(r.modifiedCount);
    },
    operations = []; // Initialise the bulk operations array

messages.forEach(function (msg) { 
    operations.push({
        "updateOne": {
            "filter": { "_id": msg._id } ,              
            "update": { "$set": { "value": msg.value } } // example update operation
        }
    });

    // Send once in 500 requests only
    if (operations.length % 500 === 0 ) {
        Model.collection.bulkWrite(
            operations, 
            { "ordered": true, w: 1 }, 
            bulkUpdateCallback
        ); 
        operations = [];
    }    
});

// Get the underlying collection via the native node.js driver collection object
Model.collection.bulkWrite(bulkOps, { "ordered": true, w: 1 }, bulkUpdateCallback); 
在上面,您初始化了更新操作数组,并将操作限制为500个批次。选择低于默认批次限制1000的值的原因通常是受控选择。如文档中所述,MongoDB默认情况下将发送到,并且不能保证这些默认的1000个操作请求实际上符合。因此,您仍然需要站在“安全”的一边,施加一个较低的批处理大小,您只能有效地管理该批处理大小,以便在发送到服务器时,其总量小于数据限制


如果您使用的是支持MongoDB Server
=2.6.x
的Mongoose
~3.8.8、~3.8.22、4.x
的旧版本,则可以使用API,如下所示

var bulk = Model.collection.initializeOrderedBulkOp(),
    bulkUpdateCallback = function(err, r){
        console.log(r.matchedCount);
        console.log(r.modifiedCount);
    },
    counter = 0;

messages.forEach(function(msg) {
    bulk.find({ "_id": msg._id }).updateOne({ 
        "$set": { "value": msg.value }
    });

    counter++;
    if (counter % 500 == 0) {
        bulk.execute(function(err, r) {
           // do something with the result
           bulk = Model.collection.initializeOrderedBulkOp();
           counter = 0;
        });
    }
});

// Catch any docs in the queue under or over the 500's
if (counter > 0) {
    bulk.execute(bulkUpdateCallback);
}

谢谢,我会努力实现这一点。