MongoDB 更新嵌套字段中的数据
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19603542/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
MongoDB update data in nested field
提问by allen wang
i'm using Mongo to be my database. i have a data:
我正在使用 Mongo 作为我的数据库。我有一个数据:
{
_id : '123'
friends: [
{name: 'allen', emails: [{email: '11111', using: 'true'}]}
]
}
now, i wanna to motify user's friends' emails ' email, whose _id is '123' i write like this:
现在,我想对主题用户的朋友的电子邮件电子邮件,其 _id 为 '123' 我这样写:
db.users.update ({_id: '123'}, {$set: {"friends.0.emails.$.email" : '2222'} })
it's easy, but , it's wrong , when the emails array has two or more data. so, my question is: how can i motify the data in a nested filed --- just have two or more nested array? Thanks.
这很容易,但是,当 emails 数组有两个或更多数据时,这是错误的。所以,我的问题是:如何在嵌套字段中对数据进行主题化——只有两个或多个嵌套数组?谢谢。
回答by Cristian Lupascu
You need to use the Dot Notationfor the arrays.
您需要对数组使用点表示法。
That is, you should replace the $
with the zero-based index of the element you're trying to update.
也就是说,您应该将 替换为$
您尝试更新的元素的从零开始的索引。
For example:
例如:
db.users.update ({_id: '123'}, { '$set': {"friends.0.emails.0.email" : '2222'} });
will update the first email of the first friend, and
将更新第一个朋友的第一封电子邮件,以及
db.users.update ({_id: '123'}, { '$set': {"friends.0.emails.1.email" : '2222'} })
will update the second email of the first friend.
将更新第一个朋友的第二封电子邮件。
回答by Kacper
Solution using Mongoose:
使用猫鼬的解决方案:
Users.findById("123", function(err, user) {
var friends = user.friends;
for ( i=0; i < friends.length; i++ ) {
if (friends[i].name == 'allen') {
friends[i].email = '2222';
user.save(function(err) {
if (err) throw err;
console.log("email updated");
});
} else {
console.log("no friends named allen");
}
}
}
回答by Eisneim
update something in a multi level arry is really pain in the ass, my way of doing it:replace the deep level arry.
在多级 arry 中更新某些东西真的很痛苦,我的做法是:替换深层 arry。
db.user.findOne({_id:'123'},{friends:1}).lean().exec(function(err,user){
var whichArrayToUpdate;
for (var ii = 0; ii < user.friends.length; ii++) {
for (var jj = 0; i < user.friends[ii].emails; jj++) {
if(user.friends[ii].emails[jj].email == '1111' ){// update it below
user.friends[ii].emails[jj].email == 'what ever you want to set to.';
whichArrayToReplace = user.friends[ii].emails;
break;
}
};
};
db.user.update({'friends.name':'allen'},{$set{'friends.$.email': whichArrayToReplace} })
})
but, why not use the save() method? the save() will replace your whole document, if your document is small that's ok, but if your document is relly big , it's a better idea to replace just part of your document.
但是,为什么不使用 save() 方法呢?save() 将替换您的整个文档,如果您的文档很小,那没关系,但如果您的文档很大,最好只替换文档的一部分。
or do the loop, use the position of the top level array and second level array(ii and jj) to update.
或者做循环,使用顶级数组和二级数组(ii和jj)的位置来更新。
my advice is: when you design schema, don't put array in another array unless you won't do any update for that array.
我的建议是:在设计架构时,不要将数组放入另一个数组中,除非您不会对该数组进行任何更新。
回答by adam
I have a similar situation where I have main category such as:
我有类似的情况,我有主要类别,例如:
{
"service": {
"isReviewed": false,
"_id": "5ea36b27d7ae560845afb88d",
"mainCategory": "message ",
"SubCategory": [
{
"priceChanged": true,
"_id": "5ea36b27d7ae560845afb88e",
"subCatPrice": "26",
"subCatName": "mustach trimming"
}
],
"shopName": "paddy the barber",
"user": "5ea1fd5b69512dc72ad2f48c",
"date_created": "2020-04-24T22:41:43.368Z",
"__v": 5
}
}
Now, it took a while figure out how to update one piece of the subdocument. as the sub doc is store as an object.
现在,花了一些时间弄清楚如何更新子文档的一部分。因为子文档存储为对象。
So All id, is first I check the _id of the doc when its passed through the put/:id. Then, I checked the owner of doc against the req.user.
所以所有的 id,首先是我在通过 put/:id 时检查文档的 _id。然后,我根据 req.user 检查了 doc 的所有者。
if everything okay, I looped through the array then I produced a new object. Then, all I did, is I check each req.body for price or name, if there is a new price, I would just update the price value in the object. if there is new value then the object remains the same.
如果一切正常,我循环遍历数组然后我生成了一个新对象。然后,我所做的就是检查每个 req.body 的价格或名称,如果有新价格,我只会更新对象中的价格值。如果有新值,则对象保持不变。
then all I said, service.SubCategory = newObject and store the data.
然后我说, service.SubCategory = newObject 并存储数据。
Its working fine, however, I ran into the problem of subdoc _id getting updated, so I fixed that by keeping the old value as its.
它工作正常,但是,我遇到了 subdoc _id 被更新的问题,所以我通过保留旧值来解决这个问题。
Now, in terms of performance and optimization, I am not entirely sure if this is the correct way but its working and if they're better away I am willing to change.
现在,在性能和优化方面,我不完全确定这是否是正确的方法,但它的工作原理,如果它们更好,我愿意改变。
Here is the code:
这是代码:
const newObject = {
subCatPrice: "",
subCatName: "",
_id: "",
priceChanged: false
};
let oldDetails = service.SubCategory;
for (const old of oldDetails) {
newObject.subCatPrice = old.subCatPrice;
newObject.subCatName = old.subCatName;
newObject._id = old._id;
}
price ? (newObject.subCatPrice = price ) && (newObject.priceChanged = true) : newObject.subCatPrice;
name ? (newObject.subCatName = name) : newObject.subCatName;
(service.SubCategory = newObject), await service.save();
I used the react idea of the state to be honest, where I just get a copy of the object and keep it and apply an update to the piece that I want to update.
老实说,我使用了 state 的 react 想法,我只是获取对象的副本并保留它,然后将更新应用到我想要更新的部分。
Again in terms of clean code and all of that stuff, I am not sure if this is the correct way to do it, but I am also a student of programming and I would like to learn too.
再次就干净的代码和所有这些东西而言,我不确定这是否是正确的方法,但我也是编程的学生,我也想学习。
Hope this help someone
希望这有助于某人