10

I have the following schema.

{
   posts: [
          {
             _id: '5ayuunbdsyuuuyut778'
             replies: [{
                 _id: "67hfudj7e9whduu888",
                 text: "something"
             }]
          }
      ]
}

I want to update the text in particular reply. I am using mongoose.

I have written the query as follows

Post.findOneAndUpdate(
   {'posts.replies._id': _id}, 
   {$set: {'posts.$[post].replies.$[reply].text': "something1"}},
   { arrayFilters: [{'post._id': postId}, { 'reply._id': _id }]}
 )

This query is not updating the document.

Am I missing something? Do I need to cast ids using ObjectId

7
  • Are you getting any error? Because above query works for me... Probably your postId or _id would not be correct... I have tried this User.findOneAndUpdate( {'posts.replies._id': "67hfudj7e9whduu888"}, {$set: {'posts.$[post].replies.$[reply].text': "something12"}}, { arrayFilters: [{'post._id': "5ayuunbdsyuuuyut778"}, { 'reply._id': "67hfudj7e9whduu888" }]} ) Commented Jul 13, 2018 at 12:31
  • which version on mongo are you using? Commented Jul 13, 2018 at 12:32
  • @Anthony Winslet. I am not getting any error. I am getting the doc without updating when I use {new:true} Commented Jul 13, 2018 at 15:14
  • are they updating in the database? And how you are using multi: true? Commented Jul 13, 2018 at 15:33
  • I haven't used multi: true. Do I need to? Commented Jul 13, 2018 at 16:31

4 Answers 4

14

You need to use new: true to get the updated value and cast id to mongoose objectId to make it work

Post.findOneAndUpdate(
   { 'posts.replies._id': _id }, 
   { $set: { 'posts.$[post].replies.$[reply].text': "something1" } },
   { arrayFilters: [{ 'post._id': postId }, { 'reply._id': _id }], new: true }
)
Sign up to request clarification or add additional context in comments.

6 Comments

It's not updating in database itself.
What I have observed is, its updating in mongo shell(3.6). but not through mongoose(5.2).
Type this command in your mongo shell db.adminCommand( { setFeatureCompatibilityVersion: "3.6" } ) and then try again
Now I am sure your id might not be correct... Put the id hard coded and try
Hey thank you for your help. I forgot to cast the Object Id in mongoose.
|
4

As arrayFilters are something related to mongodb, you need to cast id in mongoose with ObjectId

Post.findOneAndUpdate(
   { 'posts.replies._id': _id }, 
   { $set: { 'posts.$[post].replies.$[reply].text': "something1" } },
   { arrayFilters: [{ 'post._id': postId }, { 'reply._id': _id }]}
)

must be changed to

Post.findOneAndUpdate(
   { 'posts.replies._id': _id }, 
   { $set: { 'posts.$[post].replies.$[reply].text': "something1" } },
   { arrayFilters: [{ 'post._id': ObjectId(postId) }, { 'reply._id': ObjectId(_id)}]}
)

Comments

0

arrayFilters does not accept stringified Object Ids, as opposed to typical filters in mongoose (which cast object ids automatically for you), you must cast object id manually when passing it as filter to arrayFilters).

Post.findOneAndUpdate(
   { 'posts.replies._id': _id }, 
   { $set: { 'posts.$[post].replies.$[reply].text': "something1" } },
   { arrayFilters: [{ 'post._id':new ObjectId(postId) }, { 'reply._id': new ObjectId(_id) }], new: true }

this will work, check comments here for more details

Comments

0

For updating the array document, this also works for me I have a document structure like this

{
        "_id": "67c535d3252a6d096475a9c3",
        "data": {
            "resources": [
                {
                    "resourceId": "67c535d3252a6d096475a9c2",
                    "title": "Document title",
                }
            ],
        }
    },

I have the resourceId, and I have to update the with resourceId I am using this query:

await contentSchema.findOneAndUpdate(
                    {
                        _id: ObjectId('67bd63db56d56b1f7c29d455'),
                        "data.resources": {
                            $elemMatch: {
                                resourceId: ObjectId('67bd63db56d56b1f7c29d454')
                            }
                        }
                    },
                    { $set: { "data.resources.$.title": resourceTitle } },
                    {
                        new: true,
                    }
                );

Here, the $. refers to the position of the matched element in the array (the element that matched the $elemMatch condition).

I am using

  • Mongoose version: @5.12.7
  • MongoDB version: @v7.0.12

1 Comment

I don't think it works if you have multiple resources with the same resourceId. Since $ updates only the first matched element in the 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.