1

The following code works great in that it updates the object in the nested array.

However, I'm struggling to find a way to push a new object (Ex. {"locale" : "ar" , value:"مرحبا"}) if locale does not exist or update value if locale already exists (Ex. {"locale" : "en" , value:"hello"})

Update code:

    Project.findOneAndUpdate(
       {_id:projectId, 'sections._id': sectionId},
       { "$set": { "sections.$.subheader": {"locale":args.lang,"value":args.title} }},
       { upsert : true, new: true, useFindAndModify: false },
       (err, section) => {

       }
    )

Object structure:

  "project": {
      "name": "project name",
      "sections": [
        { 
          "subheader": [{

           'locale' : "en",
            'value' :  "Helle"
                      },
          {
           'locale' : "fr",
            'value' :  "salut"
                      }]

        }
      ]
    }

1 Answer 1

2

Unfortunately, this is not possible to do in one go. The upsert option only works on objects in the collection, not on nested objects.

You could solve this by first trying to update the element in the array, then check if the object in the nested array was matched. If there was no match, you can insert it into the nested array using $addToSet.

Additionally, you need to use positional operators to match the nested arrays:

Project.findOneAndUpdate(
    // match item in subheader array
    { _id: projectId, 'sections._id': sectionId, 'sections.subheader.locale': args.lang },
    // update existing item in subheader array
    { "$set": { "sections.$[section].subheader.$[subheader].value": args.title } },
    // we use arrayFilters here, don't use upsert now
    { arrayFilters: [{ 'section._id': sectionId }, { 'subheader.locale': args.lang }], useFindAndModify: false },
    (err, section) => {
        // check if section was found
        if (!section) {
            // add new object to array if it wasn't found yet
            Project.findOneAndUpdate(
                // match section
                { _id: projectId, 'sections._id': sectionId},
                // add new object to array
                { "$addToSet": { "sections.$.subheader": {"locale": args.lang,"value": args.title } }},
                (err, section) => {
                    console.log('created new locale')
                }
            )
        } else {
            console.log('updated existing locale')
        }
    }
)
Sign up to request clarification or add additional context in comments.

2 Comments

@aliAtwa what do you mean by "none of them work" - what is the result you got when trying to insert a new locale and updating an existing one? as I said, I don't have the full objects so it is a bit hard to reproduce. If you can give me a full item from your collection it will be easier for me to try the code locally.
sorry for late response, here is the problem repl.it/join/dnfrniff-alyatwa

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.