如何使用批量 read/write 将每个文档的一部分转换为每个文档中的数组?

How to transform part of each document into an array in each document using bulk read/write?

我有这样的文件

{
    "field1" : "value",
    "field3" : "value",
    "attributes" : {
        "key1" : {
            "category" : "4",
            "value" : "value"
        },
        "key2" : {
            "category" : "5",
            "value" : "value"
        },
    }
}

我想将它们转换为如下所示的结构(基本上是使用字典并将其展平为数组)。请注意 attributes 中的键数会有所不同。

{
    "field1" : "value",
    "field3" : "value",
    "attributes" : [
        {
            "key" : "key1",
            "category" : "4",
            "value" : "value"
        },
        {
            "key" : "key2",
            "category" : "5",
            "value" : "value"
        },
    ]
}

由于文档数量较多,我想使用批量API。我的脚本有这个基本结构。

db = db.getSiblingDB('MyDB');

db.MyCollection.intializeOrderedBukOp(),
var bulk = db.MyCollection.intializeOrderedBukOp(),
    count = 0;

db.MyCollection.find({}).forEach(function(doc) {
   // Re-map attrs (what follows is some pseudocode
   var attrs = function TransformSomehow(doc.attributes) {
           // return an array...
       };
   });

   // Queue update operation
   bulk.find({ "_id": doc._id })
       .updateOne({ 
           "$set": { "attrs": attrs } }
       });
   count++;

   // Execute every 1000
   if ( count % 1000 == 0 ) {
       bulk.execute();
       bulk = db.collection.intializeOrderedBukOp();
   }
});

// Drain any queued remaining
if ( count % 1000 != 0 )
    bulk.execute();

这是从 this answer 借来的,但我不能按原样使用它,因为它的方向相反(数组到对象)。看来我无法使用 map 来执行此操作。

这是使用 MongoDB NodeJS 驱动程序 v3.6 和 MongoDB v4.2.3 进行批量写入的一种方法。这使用一个简单的批处理来更新所有集合文档。更新将每个文档的对象(或字典)转换为数组(根据您的要求)。

const collection = db.collection('test');

const update1 = { 
    updateMany: { 
        filter: { }, 
        update: [ 
            { $set: { 
                 attributes: { 
                     $map: { 
                         input: { $objectToArray: "$attributes" }, 
                         in: { $mergeObjects: [ { "key": "$$this.k" }, "$$this.v" ] } 
                     } 
                 } 
            } } 
        ] 
    } 
};

collection.bulkWrite( [ update1 ],
                      { ordered: false },
                      ( err, result ) => {
                          console.log( 'Updated and modified count: ', result.matchedCount, result.modifiedCount );
                       }
)


参考: CRUD Operations - Bulk Write

@prasad_ 的回答有效。对于那些想在没有 NodeJS 的 MongoDB 控制台中应用它的人,我将他的解决方案翻译成这个。

col = db.getCollection('X');

update1 = { 
    updateMany: { 
        filter: { }, 
        update: [ 
            { $set: { 
                 attributes: { 
                     $map: { 
                         input: { $objectToArray: "$attributes" }, 
                         in: { $mergeObjects: [ { "key": "$$this.k" }, "$$this.v" ] } 
                     } 
                 } 
            } } 
        ] 
    } 
}

col.bulkWrite( [ update1 ], { ordered: false })