如何更新集合值

时间:2016-10-14 12:31:04

标签: node.js mongodb

假设我有db as;

{ name: "alex" , id: "1"}

我想要更新集合。我想加上“先生”到name字段中的值。

{ name: "Mr.alex" , id: "1"}

我该怎么做?我应该写2个查询作为;

db.collection("user").find({id : "1"}).toArray(function(err, result){
   var name = result[0].name;
   db.collection("user").updateOne({id : "1"}, {name: "Mr." + name},function(err, result){

   })
})

在mongodb中,没有更好的方法可以做x = x+1吗?

4 个答案:

答案 0 :(得分:0)

AFAIK会有两个查询,更新运营商不会获取任何字段的值并需要提供值。

但是,如果您需要为所有文档或大量文档执行此操作,则可以编写脚本并使用游标forEach并为每个文档更改名称并通过传递参数user来调用db.user.save()对象

底线保持不变。

答案 1 :(得分:0)

尝试以下:

var cursor = db.users.find({});
while (cursor.hasNext()) {
  var user = cursor.next();
  user.name = "Mr." + user.name;
  user.save();

}

无法使用一个查询。您必须遍历文档并使用更新的结果保存它们。

答案 2 :(得分:0)

目前无法在同一查询中引用检索到的文档,这样您就可以在同一操作中查找和更新文档。

因此,您必须进行多次查询才能完成您的目标:

/*
 * Single Document
 */

// I'm assuming the id field is unique and can only return one document
var doc = db.collection('user').findOne({ id: '1' });

try {
    db.collection('user').updateOne({ id: '1' }, { $set: { name: 'Mr. ' + doc.name }});
} catch (e) {
    print(e);
}

如果要处理多个更新操作,可以使用Bulk()操作构建器来执行此操作:

/*
 * Multiple Documents
 */
var bulk = db.collection('user').initializeUnorderedBulkOp();

// .forEach is synchronous in MongoDB, as it performs I/O operations
var users = db.collection('user').find({ id: { $gt: 1 } }).forEach(function(user) {
    bulk.find({ id: user.id }).update({ $set: { name: 'Mr. ' + user.name }});
});

bulk.execute();

答案 3 :(得分:0)

使用现有字段更新集合的关键是遍历从 find().toarray() 光标方法返回的数组,并使用 Bulk API更新您的集合,允许您在单个请求中(作为批处理)发送许多更新操作。

让我们通过一些例子看看这支笔是怎样的:

a)对于MongoDB服务器版本3.2及以上

db.collection("user").find({id : "1"}).toArray(function(err, result){
    var operations = [];
    result.forEach(function(doc){
        operations.push({
            "updateOne": {
                "filter": { 
                    "_id": doc._id,
                    "name": doc.name
                },
                "update": {
                    "$set": { "name": "Mr." + doc.name }
                }
            }
        }); 

        // Send once in 500 requests only
        if (operations.length % 500 === 0 ) {
            db.collection("user").bulkWrite(operations, function(err, r) {
                // do something with result
            }
            operations = [];
        }

    });

    // Clear remaining queue
    if (operations.length > 0) {
        db.collection("user").bulkWrite(operations, function(err, r) {
            // do something with result
        }
    }
})

在上文中,您初始化了您的操作数组,该数组将由Bulk API的 bulkWrite() 函数使用并保存更新操作。

然后迭代 find().toarray() 游标函数的结果,以使用更新对象创建操作数组。这些业务仅限于500批次。

选择低于默认批次限制1000的值的原因通常是受控制的选择。正如那里的文档所述,默认情况下MongoDB将发送到s erver in batches of 1000 operations at a time at maximum并且无法保证确保这些默认的1000个操作请求实际适合16MB BSON limit

所以你仍然需要在" safe"并且施加较小的批量大小,您只能有效地管理它,以便在发送到服务器时总数小于数据限制。

a)如果使用MongoDB v3.0或更低版本:

// Get the collection
var col = db.collection('user');  
// Initialize the unordered Batch
var batch = col.initializeUnorderedBulkOp();
// Initialize counter
var counter = 0;

col.find({id : "1"}).toArray(function(err, result){
    result.forEach(function(doc) {
        batch.find({ 
            "_id": doc._id,
            "name": doc.name
        }).updateOne({
            "$set": { "name": "Mr. " + doc.name }
        });
        counter++;

        if (counter % 500 === 0) {
            batch.execute(function(err, r) {
                // do something with result                           
            });
            // Re-initialize batch
            batch = col.initializeOrderedBulkOp();
        }           
    });

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