Reputation: 10929
Subdishes is a array in the item MajorFood. I want to add subdishes if they don't exist and update the subdishes if they do exist.
I tried the update method with addToSet. This works fine for a normal element but fails for an array.
MajorFood.update({'_id' : majorFoodId, 'subdishes.food' : rowVals[0]},
{$addToSet : {subdishes : {
food : rowVals[0],
energy : {
calories : s.getIntVal(rowVals[1]),
unit : rowVals[2]
}
}}}, {upsert : true}, function(err, doc){
if(err){
s.l("err update" );
callback(err);
return;
}
s.l("success");
callback();
});
The update works fine when the value food already exists in subdishes. But it crashes when an element has to be added to the array.
I am getting the following error:
MongoError: Cannot apply $addToSet to a non-array field.
Field named 'subdishes' has a non-array type Object
Is there a method to do this in a single function?
Upvotes: 1
Views: 1199
Reputation: 103305
You won't be able to do this with a single atomic update. You can use the callback in the update function to check if there has been an update and push to array if not since the document does not exist:
MajorFood.update(
{
"_id": majorFoodId,
"subdishes.food" : rowVals[0]
},
{
"$set": {
"subdishes.$": {
//without $ you get the error The dotted field is not valid for storage
"energy.$.calories": s.getIntVal(rowVals[1]),
"energy.$.unit": rowVals[2]
}
}
},
function(err, numAffected, rawResponse) {
console.log(numAffected);
console.log(rawResponse);
if (!numAffected) {
/* Push to array if subdish doesn't exist hence there's no update */
MajorFood.update(
{ "_id": majorFoodId }
{
"$push": {
"subdishes": {
"food": rowVals[0],
"energy": {
"calories": s.getIntVal(rowVals[1]),
"unit": rowVals[2]
}
}
}
},
function(err, numAffected) {
if(err){
s.l("err update" );
callback(err);
return;
}
s.l("success");
callback();
}
);
}
}
);
Upvotes: 1
Reputation: 833
May be this link can help you : mongodb addToSet a non-array field
MajorFood.update({'_id' : majorFoodId, 'subdishes.food' : {$in:[rowVals[0]]}},
{$addToSet : {subdishes : {
food : rowVals[0],
energy : {
calories : s.getIntVal(rowVals[1]),
unit : rowVals[2]
}
}}}, {upsert : true}, function(err, doc){
if(err){
s.l("err update" );
callback(err);
return;
}
s.l("success");
callback();
});
Upvotes: 0