gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 02:12:01 25 4
gpt4 key购买 nike

考虑下面的文档,如何将“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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com