Usage of $pull and $push together to modify arrays

Viewed 36

Environment: MongoDB 5.0.2

Assuming the following collection:

db.survey.drop();
db.survey.insertMany([
    {
        _id: 1,
        results: [
            { item: "A", score: 5, great: 1 },
            { item: "B", score: 8, great: 2 }
        ]
    },
    {
        _id: 2,
        results: [
            { item: "C", score: 8, great: 2 },
            { item: "B", score: 4, great: 3 }
        ]
    },
    {
        _id: 3,
        results: [
            { item: "C", score: 8, great: 4  },
            { item: "B", score: 4, great: 5  }
        ]
    }
]);

Now assume I want to change all elements of results which matching item:"B" and there I want to set the whole item to:

{ item: "B", score: 10, great: 10  }

I understand that I cannot use $addToSet because it can only match full documents.

I also understand that the following statement does not work either:

db.survey.updateMany({}, {
    $pull: {
        results: { item: "B" }
    },
    $push: {
        results: { item: "B", score: 10, great: 10  }
    }
})

...because it tells me that the combination of $pull and $push on the same element does not work:

Updating the path 'results' would create a conflict at 'results'

I understand that I can usually do this in 2 separate updateMany statement, but this violates the requirement of atomic updates, because it is not allowed that the element is in a response ever missing.

Is there an alternative which I missed so far?

1 Answers

you can try using the $ operator it finds the first label where the document is found.

db.test.updateMany({"results.item":"B"},{$set: {"results.$": { item: "B", score: 10, great: 10  }}})

i am assuming your array contains only one document where item is B . if no then to update every element you have to use this

Related