这是我收藏的文档之一

{
    "_id": ObjectId("55e86e98f493590878bb45d7"),
    "KIDS_M_0_2" : "",
    "KIDS_F_0_2" : "",
    "KIDS_U_0_2" : "Y",
    "KIDS_M_3_5" : "",
    "KIDS_F_3_5" : "",
    "KIDS_U_3_5" : "Y",
    "KIDS_M_6_10" : "",
    "KIDS_F_6_10" : "",
    "KIDS_U_6_10" : "",
    "KIDS_M_11_15" : "",
    "KIDS_F_11_15" : "",
    "KIDS_U_11_15" : "",
    "KIDS_M_16_17" : "",
    "KIDS_F_16_17" : "",
    "KIDS_U_16_17" : "Y"
}

我希望这就像
{
    "_id":ObjectId("55e86e98f493590878bb45d7"),
    "KIDS": { "KIDS_M_0_2" : "",
    "KIDS_F_0_2" : "",
    "KIDS_U_0_2" : "Y",
    "KIDS_M_3_5" : "",
    "KIDS_F_3_5" : "",
    "KIDS_U_3_5" : "Y",
    "KIDS_M_6_10" : "",
    "KIDS_F_6_10" : "",
    "KIDS_U_6_10" : "",
    "KIDS_M_11_15" : "",
    "KIDS_F_11_15" : "",
    "KIDS_U_11_15" : "",
    "KIDS_M_16_17" : "",
    "KIDS_F_16_17" : "",
    "KIDS_U_16_17" : "Y"
}

这可以通过shell完成吗,我的更新命令应该是什么。 ?

最佳答案

实际上,您需要的不仅仅是简单的命令。

您需要使用 .find() 方法通过 .forEach() 方法循环游标返回,然后使用字段的名称及其值创建一个新对象“kids”。接下来要做的是 $unset 所有字段并使用 $set 运算符创建新字段。当然你要这样做你使用 "bulk" 1 操作以获得最大效率。

var bulk = db.collection.initializeUnorderedBulkOp();
var count = 0;

db.collection.find().forEach(function(doc) {
    var kids = {};
    for(key in doc) {
        if(key != '_id' && Object.prototype.hasOwnProperty.call(doc, key)) {
            kids[key] = doc[key];
            var unset = {};
            unset[key] = '';
            bulk.find( { '_id': doc._id } ).updateOne( { '$unset': unset } );
            count++;
        }
        bulk.find( { '_id': doc._id } ).updateOne({ '$set': { 'KIDS': kids } } );
        if (count % 500 === 0) {
            bulk.execute();
            bulk = db.collection.initializeUnorderedBulkOp();
        }
})

if (count > 0)
    bulk.execute()

此操作后,您的文档如下所示:

{
        "_id" : ObjectId("567d99bcbc08a0817a1b06dd"),
        "KIDS" : {
                "KIDS_M_0_2" : "",
                "KIDS_F_0_2" : "",
                "KIDS_U_0_2" : "Y",
                "KIDS_M_3_5" : "",
                "KIDS_F_3_5" : "",
                "KIDS_U_3_5" : "Y",
                "KIDS_M_6_10" : "",
                "KIDS_F_6_10" : "",
                "KIDS_U_6_10" : "",
                "KIDS_M_11_15" : "",
                "KIDS_F_11_15" : "",
                "KIDS_U_11_15" : "",
                "KIDS_M_16_17" : "",
                "KIDS_F_16_17" : "",
                "KIDS_U_16_17" : "Y"
        }
}

MongoDB 3.2 deprecates Bulk() 及其相关方法并提供了 .bulkWrite() 方法。

var operations = [];

db.collection.find().forEach(function(doc) {
    var kids = {};
    for(var key in doc) {
        if(!key.startsWith('_id') && Object.prototype.hasOwnProperty.call(doc, key)) {
            kids[key] = doc[key];
            var unset = {};
            unset[key] = '';
            operations.push(
                { 'updateOne':
                    {
                        'filter': { '_id': doc._id } ,
                        'update': { '$unset': unset }
                    }
                }
            );
        }
        operations.push(
            { 'updateOne':
                {
                    'filter': { '_id': doc._id } ,
                    'update': { '$set': { 'KIDS': kids } }
                }
            }
        );
    }
    operations.push( { 'ordered': true } );
})

db.collection.bulkWrite(operations)

1. Bulk() API 是 2.6 版本新增的。因此,如果您使用的是旧版本,则应考虑升级

10-08 07:39