1

I have a mongoose schema of mixed types like so:

const user = mongoose.Schema({
    ...
    "links" : []
    ...

After populating this schema, I ended up with data like so:

[
    [
        {
            "step1": "post-url-google", // This field is unique for each entry
            "step2": {
                "title": "Heading 1",
                "likes": 4
            }
        },
    ],

    [
        {
            "step1": "post-url-microsoft",
            "step2": {
                "title": "Heading 1",
                "likes": 1
            }
        },

        {
            "step1": "post-url-apple",
            "step2": {
                "title": "Heading 2",
                "likes": 6 // I want to update this to 7
            }
        }
    ]
]

What I want to achieve is to update the "step1": "post-url-apple" field from 6 to have a likes of 7 So I tried using the User.save() function like so:

let user = await User.findOne({"_id" : "some_id"})

user.links[1].some(object => {
    if (object.step1 === "post-url-apple") {
        object.step2.likes = 7
        (async function (){
            user.save() // I also did error handling
        })()
        return
    }
})

This method works fine and the user gets updated but it keeps throwing ParallelSaveError possibly because I am calling the save() function in parallel on the same user instance in some other parts of my code.

So I decided to use the User.findOneAndUpdate() method, but my queries keep failing when using the mongodb dot notation $[<identifier>], obviously because I don't know how to use it properly.

Like so:

let update = {
    "$set" : { 
        "links.$[index1].$[index2].step2.likes" : 7,
    }
}

let conditions = {
    arrayFilters : [
        {"index1" : 1},
        {"index2.step1" : "post-url-apple"}
    ]
}

try {
    let result = await Users.findOneAndUpdate({"_id" : "some_id"}, update, conditions)
    console.log(result)
} catch (err) {
    console.log(err)
}

For all good reasons, I'm not hiting the catch block but the update was equally not successful

How do I achieve updating the "step1": "post-url-apple" likes field to 7 using findOneAndUpdate?

Thank you.

1 Answer 1

1

In arrayFilters you should define the conditions to be applied to all the array elements, not the index

If you are sure, you always update the second array element (index = 1) of the outer array, then you can use the dot notation for the outer array, and for the inner array you can use the array filters to get the element that has step1 = 'post-url-apple'

your code may look something like that

let update = {
    "$set" : { 
        'links.1.$[item].step2.likes': 7 // here we used links.1 to access the second element of the outer array
    }
}

let conditions = {
    arrayFilters : [
        { 'item.step1' : 'post-url-apple' } // item here is the element in the inner array that has step1 = post-url-apple
    ]
}

then do your update query

hope it helps

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

2 Comments

I tried just that but still the same odd result. Apparently the problem is from other parts of my code and not with the logic that you gave. I'll figure out what parts of the code are causing the weird behavior. Thank you.
I have solved the issue by somehow keeping track and passing the index to the update function like so: 'links.1.indexPassedToUpdateFunction.step2.likes': 7 where indexPassedToUpdateFunction = <Number>

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.