将现有字段添加到嵌套模式

时间:2016-03-11 13:02:18

标签: mongodb mongodb-query

我的数据库中包含架构文档:

var MySchema = new Schema({
  Street: { type: String },
  Age: { type: Number, default: null },
  Date: { type: Date },
  Stuff: [
       {
        _id:false, 
        ThisDate: { type: Date },
        ThisStreet: { type: String }
       }]
});

现在它是(Stuff为空):

db.person.findOne()  
    {
      Street: 'TheStreet',
      Age: 23,
      Date: ISODate("2016-02-19T00:00:00.000Z"),
      Stuff: []
    }

然后我要更新所有文件。我想要做的是将StreetDate字段移到Stuff数组中,并从架构中删除StreetDate字段。

像这样:

db.person.findOne()  
    {
      Age: 23,
      Stuff : [ 
      {
        ThisDate : ISODate("2016-02-19T00:00:00.000Z"),
        ThisStreet : "TheStreet"
      }
      ]
    }

我怎么能实现这个目标? 最诚挚的问候

2 个答案:

答案 0 :(得分:1)

由于这是“一次性”操作,我会在shell中执行,而不是使用任何其他框架。

对于MongoDB 3.2.x版本以及更多用途,bulkWrite()

var ops = [];

db.person.find({ 
    "Street": { "$exists": true },
    "Date": { "$exists": true }
}).forEach(function(doc) {
    ops.push({
        "updateOne": {
            "filter": { "_id": doc._id },
            "update": {
                "$unset": {
                    "Street": "",
                    "Date": ""
                },
                "$set": {
                    "Stuff": [{
                        "ThisDate": doc.Date,
                        "ThisStreet": doc.Street
                    }]
                }
            }
        }
    });

    if ( ops.length == 1000 ) {
        db.person.bulkWrite(ops);
        ops = [];
    }
})

if ( ops.length > 0 )
    db.person.bulkWrite(ops);

或者对于MongoDB 2.6.x和3.0.x版本,使用此版本的批量操作:

var bulk = db.person.initializeUnorderedBulkOp(),
    count = 0;

db.person.find({ 
    "Street": { "$exists": true },
    "Date": { "$exists": true }
}).forEach(function(doc) {
    bulk.find({ "_id": doc._id }).updateOne({
        "$unset": {
            "Street": "",
            "Date": ""
        },
        "$set": {
            "Stuff": [{
                "ThisDate": doc.Date,
                "ThisStreet": doc.Street
            }]
        }
    });

    if ( count % 1000 == 0 ) {
        bulk.execute();
        bulk = db.person.initializeUnorderedBulkOp();
    }
});

if ( count % 1000 != 0 )
    bulk.execute();

最重要的是,您需要迭代集合中的文档,并将其与重新排列的内容“逐一”一起写回。至少在这两种情况下使用的Bulk操作API都会减少写入和响应服务器的负担,只能处理集合中每1000个文档中的一个。

此外,不是重写整个文档,而是使用$unset删除所需的字段,而$set只是“编辑”您想要的数据

工作示例

db.person.insert(
    {
      "Street": 'TheStreet',
      "Age": 23,
      "Date": ISODate("2016-02-19T00:00:00.000Z"),
      "Stuff": []
    }
)

然后在上面运行pdate之后,结果是:

{
        "_id" : ObjectId("56e607c1ca8e7e3519b4ce93"),
        "Age" : 23,
        "Stuff" : [
                {
                        "ThisDate" : ISODate("2016-02-19T00:00:00Z"),
                        "ThisStreet" : "TheStreet"
                }
        ]
}

答案 1 :(得分:0)

我建议您使用聚合框架转换文档并按照下面的代码片段中所述进行更新

db.person.aggregate([
{$project:{Age:1, Stuff:[{Date:"$Date", Street:"$Street"}]}}
]).forEach(function(o){
  var id = o._id;
  delete o._id;
  db.person.update({_id:id, Street:{$exists: true}},o);
});

成功执行后,您的文档或文档应如下所示

{ 
    "_id" : ObjectId("56e2cd45792861e14df1f0a9"), 
    "Age" : 23.0, 
    "Stuff" : [
        {
            "Date" : ISODate("2016-02-19T00:00:00.000+0000"), 
            "Street" : "TheStreet"
        }
    ]
}