【问题标题】:In Mongodb subdocument array is there any way to add a new field in each subcoument在 Mongodb 子文档数组中,有什么方法可以在每个子文档中添加一个新字段
【发布时间】:2015-07-01 15:06:42
【问题描述】:

假设我有一个类似的文档

{
    "_id" : 5,
    "rows": [
        { "id" : "aab", "value":100},
        { "id" : "aac", "value":400},
        { "id" : "abc", "value":200},
        { "id" : "xyz", "value":300}
    ]
}

我需要在每个子文档 "status" : 1 中添加一个新键,结果应该是这样的

{
    "_id" : 5,
    "rows": [
        { "id" : "aab", "value":100, "status":1},
        { "id" : "aac", "value":400, "status":1},
        { "id" : "abc", "value":200, "status":1},
        { "id" : "xyz", "value":300, "status":1}
    ]
}

如何通过单个更新查询来做到这一点?

【问题讨论】:

    标签: arrays mongodb subdocument


    【解决方案1】:

    Mongo positional operator$elemMatch 有问题;

    $ 运算符可以更新与 $elemMatch() 运算符指定的多个查询条件匹配的第一个数组元素。

    所以这种情况下使用 mongo 查询你应该只更新特定的匹配条件。如果你在匹配中设置了rows.aac,那么你将在row.aac数组中添加status:1,检查查询如下:

    db.collectionName.update({
      "_id": 5,
      "rows": {
        "$elemMatch": {
          "id": "abc"
        }
      }
    }, {
      $set: {
        "rows.$.status": 1
      }
    }, true, false) // here you insert new field so upsert true
    

    mongo update 展示了upsertmulti 的工作原理。

    但是您仍然想更新所有文档,那么您应该使用一些programming code 或一些script。下面的代码使用 cursor forEach 更新所有数据:

    db.collectionName.find().forEach(function(data) {
      for (var ii = 0; ii < data.rows.length; ii++) {
        db.collectionName.update({
          "_id": data._id,
          "rows.id": data.rows[ii].id
        }, {
          "$set": {
            "rows.$.status": 1
          }
        }, true, false);
      }
    })
    

    如果您的文档大小更大,那么使用mongo bulk update 的更好方法将显示如何使用 mongo bulk 进行更新:

    var bulk = db.collectionName.initializeOrderedBulkOp();
    var counter = 0;
    db.collectionName.find().forEach(function(data) {
      for (var ii = 0; ii < data.rows.length; ii++) {
    
        var updatedDocument = {
          "$set": {}
        };
    
        var setStatus = "rows." + ii + ".status";
        updatedDocument["$set"][setStatus] = 101;
        // queue the update
        bulk.find({
          "_id": data._id
        }).update(updatedDocument);
        counter++;
        //  re-initialize every 1000 update statements
        if (counter % 1000 == 0) {
          bulk.execute();
          bulk = db.collectionName.initializeOrderedBulkOp();
        }
      }
    
    });
    // Add the rest in the queue
    if (counter % 1000 != 0)
      bulk.execute();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-21
      • 2017-06-13
      • 2011-12-04
      相关资源
      最近更新 更多