fpe*_*a06 9 mongoose mongodb 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")
}
Run Code Online (Sandbox Code Playgroud)
在mongo控制台我试过,这给了我好,但没有任何实际更新.
collection.update({"checkouts._id":ObjectId("55840f49e0b")},{ $rename: { "techId1": "techId" } });
Run Code Online (Sandbox Code Playgroud)
我也试过这个给我一个错误."不能使用该部分(checkouts.techId1的检查)来遍历元素"
collection.update({"checkouts._id":ObjectId("55856609e0b")},{ $rename: { "checkouts.techId1": "checkouts.techId" } })
Run Code Online (Sandbox Code Playgroud)
在猫鼬中,我尝试了以下内容.
collection.findByIdAndUpdate(id, { $rename: { "checkouts.techId1": "checkouts.techId" } }, function (err, data) {});
Run Code Online (Sandbox Code Playgroud)
和
collection.update({'checkouts._id': n1._id}, { $rename: { "checkouts.$.techId1": "checkouts.$.techId" } }, function (err, data) {});
Run Code Online (Sandbox Code Playgroud)
提前致谢.
Bla*_*ven 12
你最后很接近,但有一些东西丢失了.$rename在使用位置运算符时,您不能使用$set新名称和$unset旧名称.但是这里有另一个限制,因为它们都属于"结账"作为父路径,因为你不能同时做两件事.
你问题中的另一个核心是"遍历元素",这是你不能一次更新"全部"数组元素的一件事.好吧,不安全,无论如何都不会覆盖新数据.
您需要做的是"迭代"每个文档,并类似地迭代每个数组成员以"安全"更新.你不能真正迭代文档,并通过改动"保存"整个数组.当然不是在其他任何东西正在积极使用数据的情况下.
我个人会在MongoDB shell中运行这种操作,因为它是"一次性"(希望)的东西,这节省了编写其他API代码的开销.此外,我们在此处使用批量操作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();
Run Code Online (Sandbox Code Playgroud)
由于$set和$unset操作是成对发生的,因此我们将每个执行的总批量大小保持为1000次操作,以保持客户端的内存使用率下降.
循环只查找要重命名的字段"存在"的文档,然后迭代每个文档的每个数组元素并提交两个更改.作为批量操作,在.execute()调用之前不会将这些内容发送到服务器,其中每次调用都会返回单个响应.这节省了大量的流量.
如果你坚持用猫鼬编码.请注意,.collection从核心驱动程序获取批量API方法需要一个访问者,如下所示:
var bulk = Model.collection.inititializeOrderedBulkOp();
Run Code Online (Sandbox Code Playgroud)
发送到服务器的唯一.execute()方法是方法,所以这是你唯一的执行回调:
bulk.exectute(function(err,response) {
// code body and async iterator callback here
});
Run Code Online (Sandbox Code Playgroud)
并使用异步流量控制,而不是.forEach()如async.each.
此外,如果您这样做,那么请注意,作为不受mongoose控制的原始驱动程序方法,您不会获得与使用mongoose方法相同的数据库连接感知.除非您确定已经建立了数据库连接,否则将此代码放在服务器连接的事件回调中:
mongoose.connection.on("connect",function(err) {
// body of code
});
Run Code Online (Sandbox Code Playgroud)
但除此之外,这些是您真正需要的唯一真实(除了调用语法)更改.
| 归档时间: |
|
| 查看次数: |
3583 次 |
| 最近记录: |