Reputation: 1673
I'm trying to add a new or to update an existing SubDocument based on it's existence.
Given is the following Schema:
var providerSchema = new Schema({
provider: String,
id: String,
accessToken: Object
})
var userSchema = new Schema({
email: { type: String },
provider: [providerSchema],
created_at: Date,
updated_at: Date
});
The following Document is stored:
{
"_id": {
"$oid": "5629f57b13bc066c17b88a0d"
},
"created_at": {
"$date": "2015-10-23T08:53:15.684Z"
},
"updated_at": {
"$date": "2015-10-23T08:53:15.684Z"
},
"email": "[email protected]",
"provider": [
{
"provider": "facebook",
"id": "123123",
"accessToken": {
"expires_in": 123123,
"token_type": "bearer",
"access_token": "123123123"
},
"_id": {
"$oid": "5629f57b13bc066c17b88a0e"
}
},
{
"accessToken": {
"access_token": "123123",
"token_type": "bearer",
"uid": "123123"
},
"id": "123123",
"provider": "dropbox",
"_id": {
"$oid": "5629f58813bc066c17b88a12"
}
}
],
"__v": 0
}
I'm trying to update or to add the new SubDocument with the following code:
User.findOneAndUpdate({email: email},
{
"$push" : {
"provider": {
"provider": "dropbox",
"id": "123441212",
"accessToken": "sdasddad"
}
}
}, function (error, doc) {
....
}});
Unfortunately the existing SubDocuments aren't updated but new SubDocuments are created.
Could you please help me?
Thanks in advance!
P.s. Is it possible to have named SubDocuments? So for example to have a SubDocument called "facebook" which is accessible directly via name?
--- Solution ---
User.findOne(
{"email": email})
.populate("provider")
.exec(function (err, data) {
if(data === null && typeof data === "object"){
// Create User
user.save(function (error) {
if(error) return callback(new Error(error), null);
return callback(null, user);
})
} else {
//
if(err) return callback(new Error(err), null);
var prov = _.findWhere(data.provider, { "provider": provider });
if(typeof variable_here === 'undefined'){
data.provider.push(update);
} else {
_.extend(prov, update);
}
data.save(function (error) {
if(error) {
return callback(error, null);
} else {
return callback(null, data);
}
});
}
}
);
Thanks, Hossein Gerami! Still a lot of fallbacks ...
(I struggled at first with "_.findWhere"; it's underscore; just install via "npm install underscore --save" and put the following line in your file "var _ = require('underscore');")
Upvotes: 3
Views: 2690
Reputation: 1673
--- Solution ---
User.findOne(
{"email": email})
.populate("provider")
.exec(function (err, data) {
if(data === null && typeof data === "object"){
// Create User
user.save(function (error) {
if(error) return callback(new Error(error), null);
return callback(null, user);
})
} else {
//
if(err) return callback(new Error(err), null);
var prov = _.findWhere(data.provider, { "provider": provider });
if(typeof variable_here === 'undefined'){
data.provider.push(update);
} else {
_.extend(prov, update);
}
data.save(function (error) {
if(error) {
return callback(error, null);
} else {
return callback(null, data);
}
});
}
}
);
Thanks, Hossein Gerami! Still a lot of fallbacks ...
(I struggled at first with "_.findWhere"; it's underscore; just install via "npm install underscore --save" and put the following line in your file "var _ = require('underscore');")
Upvotes: 0
Reputation: 1126
Consider the following document in the students collection whose grades element value is an array of embedded documents:
{
_id: 4,
grades: [
{ grade: 80, mean: 75, std: 8 },
{ grade: 85, mean: 90, std: 5 },
{ grade: 90, mean: 85, std: 3 }
]
}
Use the positional $ operator to update the value of the std field in the embedded document with the grade of 85:
db.students.update(
{ _id: 4, "grades.grade": 85 },
{ $set: { "grades.$.std" : 6 } }
)
Below code is the complete syntax for update in the following if you define upsert as true it will insert new record other wise it will be updated. Default Value : false
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
Upvotes: 1
Reputation: 588
You can try this. I think this may work.
User.update({email: email,provider.provider:'dropbox'},{$set:{"provider.$": {"provider": {
"provider": "dropbox",
"id": "123441212",
"accessToken": "sdasddad"
}}}},function(error, doc){
...
}});
Upvotes: 0