Mongodb将多个对象永久地转换为数组

时间:2018-01-11 15:30:44

标签: mongodb aggregation-framework

我有一个包含此表单文档的集合:

{
    "name" : "John Smith",    
    "store_affiliation" : {
        "stores" : {
            "ABCD" : {
                "role" : "General Manager", 
                "startdate" : ISODate("1970-01-01T00:00:00.000+0000"), 
                "enddate" : ISODate("1980-01-01T00:00:00.000+0000"), 
                "permissions" : "GM"
            }, 
            "1234" : {
                "role" : "Owner", 
                "startdate" : ISODate("1970-01-01T00:00:00.000+0000"), 
                "enddate" : null, 
                "permissions" : "ALL"
            }, 
            "4321" : {
                "role" : "Owner", 
                "startdate" : ISODate("1990-01-01T00:00:00.000+0000"), 
                "enddate" : null, 
                "permissions" : "ALL"
            }
        }
}

...但我需要以这种形式存储的商店列表(“商店”数组):

{ "name" : "John Smith",
  "store_affiliation" : {
        "stores" : [
            {
                "store_code" : "ABCD", 
                "role" : "General Manager", 
                "startdate" : ISODate("1970-01-01T00:00:00.000+0000"), 
                "enddate" : ISODate("1980-01-01T00:00:00.000+0000"), 
                "permissions" : "GM"
            }, 
            {
                "store_code" : "1234", 
                "role" : "Owner", 
                "startdate" : ISODate("1970-01-01T00:00:00.000+0000"), 
                "enddate" : null, 
                "permissions" : "ALL"
            }, 
            {
                "shop_id" : "4321", 
                "role" : "Owner", 
                "startdate" : ISODate("1990-01-01T00:00:00.000+0000"), 
                "enddate" : null, 
                "permissions" : "ALL"
            }
        ]
}

我已经在$project管道中使用$group$pushaggregate进行了研究,但我觉得使用aggregate甚至可能是死路一条,因为我不是在查询结果之后;我正在尝试永久修改集合中的每个文档(数千个)。

1 个答案:

答案 0 :(得分:3)

您可以在3.4版本中尝试以下聚合管道。

下面的聚合将stores嵌入文档更改为键值对数组,使用$objectToArray后跟$map输出带有新字段的转换数组,同时保留所有现有字段。

批量更新以编写新商店结构。

var bulk = db.getCollection(col).initializeUnorderedBulkOp();
var count = 0;
var batch = 1;

db.getCollection(col).aggregate([
{"$match":{"store_affiliation.stores":{"$ne":{"$type":4}}}},
{"$addFields":{
  "stores":{
      "$map":{
        "input":{"$objectToArray": "$store_affiliation.stores"}, 
        "in":{
           "store_code":"$$this.k", 
           "role":"$$this.v.role", 
           "startdate":"$$this.v.startdate", 
           "enddate":"$$this.v.enddate", 
           "permissions":"$$this.v.permissions"
         }
      }
    }
}}]).forEach(function(doc){ 
    var _id = doc._id; 
    var stores = doc.stores; 
    bulk.find({ "_id" : _id }).updateOne(
      { $set: {"store_affiliation.stores" : stores} }
   ); 
    count++;  
    if (count == batch) { 
        bulk.execute(); 
        bulk = db.getCollection(col).initializeUnorderedBulkOp(); 
        count = 0;
    } 
});

if (count > 0) { 
    bulk.execute(); 
}