My document structure is as follows
{
"_id": {
"$oid": "55ae24016fb73f6ac7c2d640"
},
"Name": "some name",
"District": "some district",
"Stories": [
{
"userId": "105304831528398207103",
"story": "some story",
"Likes": ["user id 1" ..... ],
"_id": {
"$oid": "55c055af1875b0002572cf94"
}
}
]
}
Now when a user likes a story, i want to add his user id to the array Likes
I tried the following code
router.post("/NewStoryLike", function (req, res) {
var mongo = require('mongodb');
var db = require('monk');
var ObjectID = mongo.ObjectID;
req.db.get('clnTemple').findAndModify({
query: { "_id": ObjectID(req.body.postId) ,"Stories._id": ObjectID(req.body.storyId) },
update: { $addToSet: { Likes: req.body.userId } },
upsert: true
});
res.send("Like Added");
});
Its not throwing any errors but its not adding user id to likes array, instead it is adding an Likes in top level, i.e its adding to post level
What change should be made?
So using nested arrays is a bad idea for design. This is because of the limitations of what you can do with array updates in MongoDB. As stated in the documentation for the positional $
update operator:
Nested Arrays
The positional $ operator cannot be used for queries which traverse more than one array, such as queries that traverse arrays nested within other arrays, because the replacement for the $ placeholder is a single value
It is perfectly fine however to just $push|$addToSet
where the only array you are actually matching is the outer array and therefore the "first" array element matched. As long as you have your naming correct:
req.db.get('clnTemple').findAndModify({
{
"_id": req.body.postId ,
"Stories._id": ObjectID(req.body.storyId),
},
{ "$addToSet": { "Stories.$.Likes": req.body.userId } },
{ "new": true },
function(err,doc) {
// updted doc in here
}
);
Aside from that you should not really be using nested arrays, this will work just fine, since it is only appending to the "inner" array of the matched "outer" array.
As a personal preference, I model "Likes" much more differently and much more reliably. But that is another question.