1

I have tried the below query of mongoose which does not seem to work:

Model.findOneAndUpdate(
    {
        name: origin
    },
    {
        $set: {
            'field1.$[id1].field2.-1': "value"
        }
    },
    {
        arrayFilters: [
            { 'id1.userId': "customerId" }
        ],
        new: true
    }
);

Note: field1 and field2 are arrays

The negative indexes are not accepted by MongoDB which is causing problems.

2 Answers 2

1

You may consider using the $set (aggregation) operator and use double $map operator:

db.collection.aggregate([
    { $match: { name: "myname" } }
    {
        $set: {
            field1: {
                $map: {
                    input: "$field1",
                    in: {
                        $cond: {
                            if: { $ne: [ "$$this.userId", "customerId" ] },
                            then: "$$this",
                            else: {
                                $mergeObjects: [
                                    "$$this",
                                    { 
                                        field2: { 
                                            $concatArrays: [
                                                { $slice: [ "$$this.field2", { $add: [ { $size: "$$this.field2" }, -1 ] } ] },
                                                ["value"]
                                            ]
                                        } 
                                    }
                                ]
                            }
                        }
                    }
                }
            }
        }
    }
])

Mongo Playground

Sign up to request clarification or add additional context in comments.

5 Comments

This solution does the job. However, the issue here is that this will map through every element even after the required element is updated. Is there a way to optimize this query further? (There will only be 1 element which will satisfy the condition)
@ABHISHEKJoshi no other single round-trip solution comes to my mind, you can wait for others to respond. Since negative indexes are not allowed you need to know the index of your last element and this requires to query the document first. In my solution everything is processed on the database side
I'm getting this error: MongoServerError: Updating the path 'analysis' would create a conflict at 'analysis'. Please note that I'm using findOneAndUpdate() and not aggregate().
@ABHISHEKJoshi I think it requires aggregate
Actually I wanted updated document to be returned. That's the reason I used findOneAndUpdate. Maybe I'll have to query the DB twice. I guess that's the only way to go.
0

Apply the $set operator together with the $ positional operator in your update to change the name field.

The $ positional operator will identify the correct element in the array to update without explicitly specifying the position of the element in the array, thus your final update statement should look like:

db.collection.update(
    { "friends.u.username": "michael" }, 
    { "$set": { "friends.$.u.name": "hello" } }
)

Answer taken from - https://stackoverflow.com/a/34431571

1 Comment

As mentioned in the title, I want to update last element of nested array. Your solution updates any element which satisfies the condition in 1st argument of the update function and not specifically the last element. So this cannot be a valid solution.

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.