mongodb - 重命名数组中的子文档字段

标签 mongodb mongoose mongodb-query

考虑下面的文档,如何将“techId1”重命名为“techId”。我尝试了不同的方法,但无法使其发挥作用。

{
        "_id" : ObjectId("55840f49e0b"),
        "__v" : 0,
        "accessCard" : "123456789",
        "checkouts" : [ 
            {
                "user" : ObjectId("5571e7619f"),
                "_id" : ObjectId("55840f49e0bf"),
                "date" : ISODate("2015-06-19T12:45:52.339Z"),
                "techId1" : ObjectId("553d9cbcaf")
            }, 
            {
                "user" : ObjectId("5571e7619f15"),
                "_id" : ObjectId("55880e8ee0bf"),
                "date" : ISODate("2015-06-22T13:01:51.672Z"),
                "techId1" : ObjectId("55b7db39989")
            }
        ],
        "created" : ISODate("2015-06-19T12:47:05.422Z"),
        "date" : ISODate("2015-06-19T12:45:52.339Z"),
        "location" : ObjectId("55743c8ddbda"),
        "model" : "model1",
        "order" : ObjectId("55840f49e0bf"),
        "rid" : "987654321",
        "serialNumber" : "AHSJSHSKSK",
        "user" : ObjectId("5571e7619f1"),
        "techId" : ObjectId("55b7db399")
    }

在 mongo 控制台中,我尝试了,这让我可以,但实际上没有任何更新。

collection.update({"checkouts._id":ObjectId("55840f49e0b")},{ $rename: { "techId1": "techId" } });

我也尝试过这个,这给了我一个错误。 “无法使用该部分(checkouts.techId1 的 checkout )来遍历该元素”

collection.update({"checkouts._id":ObjectId("55856609e0b")},{ $rename: { "checkouts.techId1": "checkouts.techId" } })

在 Mongoose 中,我尝试了以下操作。

collection.findByIdAndUpdate(id, { $rename: { "checkouts.techId1": "checkouts.techId" } }, function (err, data) {});

collection.update({'checkouts._id': n1._id}, { $rename: { "checkouts.$.techId1": "checkouts.$.techId" } }, function (err, data) {});

提前致谢。

最佳答案

最后你已经很接近了,但是还缺少一些东西。你不能$rename当使用位置运算符时,您需要 $set新名称和 $unset旧的。但这里还有另一个限制,因为它们都属于“checkouts”作为父路径,因此您不能同时执行这两个操作。

您问题中的另一条核心线是“遍历元素”,这是您无法一次性更新“所有”数组元素的一件事。嗯,不安全,而且也不可能覆盖传入的新数据。

您需要做的是“迭代”每个文档并类似地迭代每个数组成员以便“安全”更新。您不能真正只迭代文档并通过更改“保存”整个数组。当然不是在其他任何东西正在积极使用数据的情况下。

如果可以的话,我个人会在 MongoDB shell 中运行这种操作,因为它是“一次性”(希望如此)的事情,这样可以节省编写其他 API 代码的开销。我们还使用 Bulk Operations API在这里尽可能提高效率。对于 Mongoose 来说,需要更多的挖掘来实现,但仍然可以完成。但这里是 shell 列表:

var bulk = db.collection.initializeOrderedBulkOp(),
    count = 0;

db.collection.find({ "checkouts.techId1": { "$exists": true } }).forEach(function(doc) {
    doc.checkouts.forEach(function(checkout) {
        if ( checkout.hasOwnProperty("techId1") ) { 
            bulk.find({ "_id": doc._id, "checkouts._id": checkout._id }).updateOne({
                "$set": { "checkouts.$.techId": checkout.techId1 }
            });
            bulk.find({ "_id": doc._id, "checkouts._id": checkout._id }).updateOne({
                "$unset": { "checkouts.$.techId1": 1 }
            });
            count += 2;

            if ( count % 500 == 0 ) {
                bulk.execute();
                bulk = db.collection.initializeOrderedBulkOp();
            }
        }
    });
});

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

由于 $set$unset 操作成对发生,我们将每次执行的总批处理大小保持在 1000 个操作,只是为了保持客户端的内存使用量下来。

该循环只是查找“存在”要重命名的字段的文档,然后迭代每个文档的每个数组元素并提交两个更改。作为批量操作,这些操作在调用 .execute() 之前不会发送到服务器,其中每个调用都会返回一个响应。这节省了大量流量。

如果你坚持使用 Mongoose 编码。请注意,需要 .collection 访问器才能从核心驱动程序获取批量 API 方法,如下所示:

var bulk = Model.collection.inititializeOrderedBulkOp();

发送到服务器的唯一内容是 .execute() 方法,因此这是您唯一的执行回调:

bulk.exectute(function(err,response) {
    // code body and async iterator callback here
});

并使用异步流控制而不是 .forEach() 例如 async.each .

此外,如果您这样做,请注意,作为不受 mongoose 控制的原始驱动程序方法,您无法获得与 mongoose 方法相同的数据库连接感知。除非您确定数据库连接已建立,否则将此代码放入服务器连接的事件回调中会更安全:

mongoose.connection.on("connect",function(err) {
    // body of code
});

但除此之外,这些是您真正需要的唯一真正的(除了调用语法之外)更改。

关于mongodb - 重命名数组中的子文档字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31688122/

相关文章:

node.js - Mongoose 错误 - 升级后没有 'toObject' 方法

node.js - MongoDB - 找到至少一个数组值丢失的地方

node.js - 如何在 NestJS 上为 MongoDB 实现存储库设计模式

node.js - 无法从 Mongoose 访问 populate() 对象的属性?

mongodb - 在对象数组中查找具有两个特定 ID 的所有文档。数据库

node.js - MongoDB,有没有一种方法可以在更新文档之前添加新字段?

mongodb - Mongodb聚合$ group,限制数组的长度

ruby - 如何在同一个 Ruby Rails 项目中配置 MongoMapper 和 ActiveRecord

mongodb - MongoDB : how to use refs to documents in other collections 中缺少类似连接查询的数据库设计

arrays - 在 mongo 数组中查找平均天数