Mehran Ishanian
Mehran Ishanian

Reputation: 441

Mongoose update subdocument by key

for the following collection:

id: Number
name:[ 
       new Schema({
           language: { type: String, enum: ['en-US', 'fr-CA'] },
           text: String,
       },{ _id: false }
       );
     ],
isActive: Boolean

and sample data like the following:

{
  id:1,
  "name": [
            {"language": "en-US", "text": "Book"},
            {"language": "fr-CA", "text": "livre"}
          ],
   isActive:true
   // and so many other fields
},
{
  id:2,
  "name": [
            {"language": "en-US", "text": "Pen"}
          ],
   isActive:true
   // and so many other fields
}

I would like to update the document by Id:1 and change the text only for french, I tried by:

const input={ "id":"1", "isActive": false}
const name= { "name": [{"language": "fr-CA", "text": "Nouvel article"}]}
await langs.findByIdAndUpdate(
    { _id: input.id },
    { ...input, $addToSet: { name } },
    { new: true, upsert: true }
  );

but the result is: (added another french item)

{
  id:1,
  "name": [
            {"language": "en-US", "text": "Book"},
            {"language": "fr-CA", "text": "livre"},
            {"language": "fr-CA", "text": "Nouvel article"}
          ],
   isActive:false
},

This is based on Brit comment:

https://mongoplayground.net/p/atlw5ZKoYiI

Please advise.

Upvotes: 0

Views: 198

Answers (1)

Thunder Cat King
Thunder Cat King

Reputation: 662

As long as that attribute already exists on the document, you can do something like:

   Collection.findOneAndUpdate({id: 1}, {
        $set: {
          "name.$[elem]": name
        }
      },
      {
        arrayFilters: [  { "elem.language":  name.language  } ],
        upsert: true,
        new: true
      })

Upvotes: 1

Related Questions