Home > other >  Issue using $pull from nested Mongoose array atomic operation
Issue using $pull from nested Mongoose array atomic operation

Time:11-10

I can't seem to get this mongoose $pull operation to work at all. I have tried many solutions, but would ultimately like to use an atomic operation to achieve this as that is the design pattern in the rest of my code.

In my List schema, I have an array of Item objects. Each Item object has an array of Notes which are all string values. Creating, Reading, and Updating these Notes arrays has been no issue. But I can't seem to get the Delete functionality to work.

Schemas:

List

const listSchema = mongoose.Schema({
    user: {
        type: mongoose.Schema.Types.ObjectId,
        ref: "Users"
    },
    name: {
        type: String
    },
    items: {
        type: Array,
        default: [itemSchema]
    }
  });

Item

const itemsSchema = {
    item: String,
    style: String,
    moved: Boolean,
    notes: Array
};

Sample Document:

_id: 6186940ce10fbd7cec9fb01f
    items: Array
        0: Object
            notes: Array
                0: "Updated again x2"
                1: "Test one to delete edit"
                2: "New one"
            _id: 6186d98dcef2ae43605becc4
            item: "Test 1"
            style: ""
            moved: false
        1: Object
            notes: Array
            _id: 6186d98fcef2ae43605becc5
            item: "Test 2"
            style: ""
            moved: false
        2: Object
            notes: Array
            _id: 6186d991cef2ae43605becc6
            item: "Test 3"
            style: ""
            moved: false
        3: Object
            notes: Array
                0: "Add from none"
                1: "typing a really long sentence here to see what happens when I get to t..."
                2: "Test"
            _id: 6186d994cef2ae43605becc7
            item: "Test 4"
            style: ""
            moved: false
    user: 611083d8baed4458d8dcd273
    name: "Nov-06-2021"
    __v: 0

Methods:

Create

List.findOneAndUpdate(
    { "user": req.user.id, "name": list, "items._id": ObjectId(id) },
    { "$push": { "items.$.notes": newNote } },
    { new: true },
    (err, newList) => {}
)

Update

List.findOneAndUpdate(
    { "user": req.user.id, "name": list, "items._id": ObjectId(id) },
    { "$set": { "items.$.notes.$[note]": newNoteText } },
    { 
        arrayFilters: [{"note": note}],
        new: true 
    },
    (err, newList) => {}
)

Delete (not working)

List.findOneAndUpdate(
    { "user": req.user.id, "name": list, "items._id": ObjectId(id) },
    { "$pull": { "items.$.notes.$[note]": note } },
    { 
        arrayFilters: [{"note": note}],
        new: true 
    },
    (err, newList) => {}
)

The current Delete code block is close to what I'd like my solution to look like. By all rights, and everything I've read, it should already work. Can anyone show me what will work, and possibly why this isn't currently working?

I have tried many solutions including using $in, $[], $elemMatch, and a bunch more outside the box solutions. I don't see why $push and $set work without issue, but $pull is deciding to do nothing.

The current response I get from MongoDb with this operation doesn't include an error message, but the returned newList is a null value, and no change is reflected in my DB. I am currently on the latest version of mongoose: 5.13.13.

CodePudding user response:

The solution to this was to remove the $[note]from my operator as $pull requires an array to operate on, not the array object.

I definitely tried that before, before there was an issue with my request body that was coming from the front end. I wasn't using the correct syntax for an axios.delete, however, and that was my main issue.

Solution

List.findOneAndUpdate(
    { "user": req.user.id, "name": list, "items._id": ObjectId(id) },
    { "$pull": { "items.$.notes": note } },
    { new: true },
    (err, newList) => {}
)

I removed $[note] as a variable because $pull operates on the entire notes array. Therefore, I no longer need the arrayFilters because it is already looking for the note variable.

  • Related