Home > Software engineering >  How can I find specific document and update a value of specific key inside array?
How can I find specific document and update a value of specific key inside array?

Time:11-07

I have a structure like this:

{
  _id: new ObjectId("634aa49f98e3a05346dd2327"),
  filmName: 'Film number 1',
  episodes: [
    {
      episodeName: 'Testing 1',
      slugEpisode: 'testing-1',
      _id: new ObjectId("6351395c17f08335f1dabfc9")
    },
    {
      episodeName: 'Testing 2',
      slugEpisode: 'testing-2',
      _id: new ObjectId("6351399d9a2533b9be1cbab0")
    },
  ],
},
{
  _id: new ObjectId("634aa4cc98e3a05346dd232a"),
  filmName: 'Film number 2',
  episodes: [
    {
      episodeName: 'Something 1',
      slugEpisode: 'something-1',
      _id: new ObjectId("6367cce66d6b85442f850b3a")
    },
    {
      episodeName: 'Something 2',
      slugEpisode: 'something-2',
      _id: new ObjectId("6367cd0e6d6b85442f850b3e")
    },
  ],
}

I received 3 fields:

  • _id: Film _id
  • episodeId: Episode _id
  • episodeName: The content I wish to update

I tried to find a specific Film ID to get a specific film, and from then on, I pass an Episode ID to find the exact episode in the episodes array. Then, update the episodeName of that specific episode.

Here's my code in NodeJS:

editEpisode: async (req, res) => {
    const { _id } = req.params
    const { episodeId, episodeName } = req.body

    try {
        const specificResult = await Films.findOneAndUpdate(
            { _id, 'episodes._id': episodeId },
            { episodeName }
        )

        console.log(specificResult)
        res.json({ msg: "Success update episode name" })
    } catch (err) {
        return res.status(500).json({ msg: err.message })
    }
},

But what console.log display to me is a whole document, and when I check in MongoDB, there was no update at all, does my way of using findOneAndUpdate incorrect?

I'm reading this document: MongooseJS - Find One and Update, they said this one gives me the option to filter and update.

CodePudding user response:

The MongoDB server needs to know which array element to update. If there is just one array element to update, here's one way you could do it. (I picked a specific element. You would use your req.params and req.body.)

db.films.update({
  "_id": ObjectId("634aa4cc98e3a05346dd232a"),
  "episodes._id": ObjectId("6367cd0e6d6b85442f850b3e")
},
{
  "$set": {
    "episodes.$.episodeName": "Something Two"
  }
})

Try it on mongoplayground.net.

CodePudding user response:

You can use the filtered positional operator $[<identifier>] which essentially finds the element or object (in your case) with a filter condition and updates that.

Query:

const { _id } = req.params
const { episodeId, episodeName } = req.body

await Films.update({
  "_id": _id
},
{
  $set: {
    "episodes.$[elem].episodeName": episodeName
  }
},
{
  arrayFilters: [
    {
      "elem._id": episodeId
    }
  ]
})

Check it out here for example purpose I've put ids as numbers and episode name to update as "UpdatedValue"

  • Related