gpt4 book ai didi

javascript - 如何最高效地更新MongoDB中的大量文档?

转载 作者:可可西里 更新时间:2023-11-01 09:57:01 25 4
gpt4 key购买 nike

我想最有效地更新大量(> 100,000)文档。

我的第一个天真的方法是在 JS 级别上进行,编写脚本首先获取 _ids,然后遍历 _ids 并通过 _id 调用更新(完整文档或 $set 补丁)。

我遇到了内存问题,还将数据分成最大块。 500文档(打开和关闭连接)似乎效果不佳。

那么我该如何在 MongoDB 级别解决这个问题呢?
最佳实践?

我有 3 个常见用例,通常是维护工作流程:

<强>1。更改属性值的类型,但不更改值。

// before
{
timestamp : '1446987395'
}

// after
{
timestamp : 1446987395
}

<强>2。根据现有属性的值添加新属性。

// before
{
firstname : 'John',
lastname : 'Doe'
}

// after
{
firstname : 'John',
lastname : 'Doe',
name : 'John Doe'
}

<强>3。只需添加从文档中删除属性。

// before
{
street : 'Whatever Ave',
street_no : '1025'
}

// after
{
street : 'Whatever Ave',
no : '1025'
}

感谢您的帮助。

最佳答案

如果您的 MongoDB 服务器是 2.6 或更新版本,最好利用写入命令 Bulk API 允许批量执行 update 操作是服务器之上的简单抽象,可以轻松构建批量操作。这些批量操作主要有两种形式:

  • 订购批量操作。这些操作按顺序执行所有操作,并在第一次写入错误时出错。
  • 无序批量操作。这些操作并行执行所有操作并汇总所有错误。无序批量操作不保证执行顺序。

请注意,对于低于 2.6 的旧服务器,API 将对操作进行下转换。但是,不可能 100% 下转换,因此可能存在一些无法正确报告正确数字的边缘情况。

对于您的三个常见用例,您可以像这样实现批量 API:

案例 1.更改属性值的类型,但不更改值:

var MongoClient = require('mongodb').MongoClient;

MongoClient.connect("mongodb://localhost:27017/test", function(err, db) {
// Handle error
if(err) throw err;

// Get the collection and bulk api artefacts
var col = db.collection('users'),
bulk = col.initializeOrderedBulkOp(), // Initialize the Ordered Batch
counter = 0;

// Case 1. Change type of value of property, without changing the value.
col.find({"timestamp": {"$exists": true, "$type": 2} }).each(function (err, doc) {

var newTimestamp = parseInt(doc.timestamp);
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "timestamp": newTimestamp }
});

counter++;

if (counter % 1000 == 0 ) {
bulk.execute(function(err, result) {
// re-initialise batch operation
bulk = col.initializeOrderedBulkOp();
});
}
});

if (counter % 1000 != 0 ){
bulk.execute(function(err, result) {
// do something with result
db.close();
});
}
});

案例 2. 根据现有属性的值添加新属性:

MongoClient.connect("mongodb://localhost:27017/test", function(err, db) {
// Handle error
if(err) throw err;

// Get the collection and bulk api artefacts
var col = db.collection('users'),
bulk = col.initializeOrderedBulkOp(), // Initialize the Ordered Batch
counter = 0;

// Case 2. Add new property based on value of existing property.
col.find({"name": {"$exists": false } }).each(function (err, doc) {

var fullName = doc.firstname + " " doc.lastname;
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "name": fullName }
});

counter++;

if (counter % 1000 == 0 ) {
bulk.execute(function(err, result) {
// re-initialise batch operation
bulk = col.initializeOrderedBulkOp();
});
}
});

if (counter % 1000 != 0 ){
bulk.execute(function(err, result) {
// do something with result
db.close();
});
}
});

案例 3. 简单地添加从文档中删除属性。

MongoClient.connect("mongodb://localhost:27017/test", function(err, db) {
// Handle error
if(err) throw err;

// Get the collection and bulk api artefacts
var col = db.collection('users'),
bulk = col.initializeOrderedBulkOp(), // Initialize the Ordered Batch
counter = 0;

// Case 3. Simply adding removing properties from documents.
col.find({"street_no": {"$exists": true } }).each(function (err, doc) {

bulk.find({ "_id": doc._id }).updateOne({
"$set": { "no": doc.street_no },
"$unset": { "street_no": "" }
});

counter++;

if (counter % 1000 == 0 ) {
bulk.execute(function(err, result) {
// re-initialise batch operation
bulk = col.initializeOrderedBulkOp();
});
}
});

if (counter % 1000 != 0 ){
bulk.execute(function(err, result) {
// do something with result
db.close();
});
}
});

关于javascript - 如何最高效地更新MongoDB中的大量文档?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33594397/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com