I'm using Node JS with Mongoose fyi. Given I've something like this:-
let people = [
{
"_id": 1,
"name": "Person 1",
"pets": [
{
"_id": 1,
"name": "Tom",
"category": "cat",
"favFood": [
{
"_id": 1,
"name": "steamed fish"
}
]
},
{
"_id": 2,
"name": "Jerry",
"category": "mouse",
"favFood": [
{
"_id": 1,
"name": "cheese"
}
]
}
]
}
]
Right now I know how to insert
new pet
data like shown below:-
// new Pet Data to INSERT
let newPetData = {
name: "Butch",
category: "dog",
favFood: [
{
name: "bone"
}
]
}
// INSERT new data in DB
People.updateOne(
// push into the sub-documents - pets
{ $push: { pets: newPetData } },
(err, success) => {
if(err) res.json({ message: `Unsuccessful!`, report: err })
else res.json({ message: `Successful!`, report: success })
}
)
But how can I insert new favFood
data of a pet
if I have their id
(id of the pet)?
let petID = 1 // this is the ID of pet named Tom
// this is a new favorite food of Tom to INSERT
let newFavFood = {
name: "fried fish"
}
// code to INSERT new favorite food of Tom (THIS DOES NOT WORK!)
People.updateOne(
{ "_id": petID } // id of pet 'Tom'
{ $push: { favFood: newFavFood } }, // push into the sub-documents - favFood
(err, success) => {
if(err) res.json({ message: `Unsuccessful!`, report: err })
else res.json({ message: `Successful!`, report: success })
}
)
The above code does not work. I thought that if I specify the id
of a pet like show above { "_id": petID }
would yield what I want. Even though it returns a message
of Successful!
. But still no new record added to the db itself. The result I'm seeking of would be something shown below:-
let people = [
{
"_id": 1,
"name": "Person 1",
"pets": [
{
"_id": 1,
"name": "Tom",
"category": "cat",
"favFood": [
{
"_id": 1,
"name": "steamed fish"
},
{
"_id": 2,
"name": "fried fish" // this is the new data inserted
}
]
},
{
"_id": 2,
"name": "Jerry",
"category": "mouse",
"favFood": [
{
"_id": 1,
"name": "cheese"
}
]
}
]
}
]
is there any other way I can do this? Do I have to implement $elemMatch
in this? If so, how can I do that here?
The query part matches documents, not elements, so { "_id": petID }
is matching the person's _id. To match the pet's, use dotted notation like { "pets._id": petID }
Then use the positional operator $
to reference the first array element that matched the query part:
.updateOne(
{ "pets._id": petID },
{ $push: { "pets.$.favFood": newFavFood }}
)