0

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?

1 Answer 1

1

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 }}
)
Sign up to request clarification or add additional context in comments.

4 Comments

What do you mean by 'using positional operator $ to reference the first array element that matched the query part'?
In the example, the query part { "pets._id": petID } matches the _id field of an element of the pets array. In the update part pets.$ refers to the first element in the pets array that satisfied the query part. See docs.mongodb.com/manual/reference/operator/update/positional/…
It said it here in the documentation you just gave me that if I were to have one more nested array that comes after favFood array like for example: favFood [{ _id: 1, name: Fried fish, Nutrition: [{ _id: 1, name: Vit A }, { _id: 1, name: Vit B }] }]. I added new array called Nutrition inside favFood array. So I can't use this method if I want to push new data to Nutrition array? Do you have any documentation I can refer to for this kind of operation?
In that case, you will need to use array filters, and specify a filter for each array

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.