Brandon
Brandon

Reputation: 3891

Remove sub-document from Mongo with mongoose

I am trying to remove an item from a collection that is stored in a mongoose document. My document looks like this:

{
  "__v": 3,
  "_id": "5221040475f174d59a000005",
  "items": [
    {
      "sku": 1321654654613213,
      "name": "goldfish",
      "quantity": 12,
      "_id": "52224ed5bd9d340000000003"
    },
    {
      "sku": 12,
      "name": "goldfish",
      "quantity": 13,
      "_id": "52225dcbf2f1e40000000003"
    },
    {
      "sku": 1299,
      "name": "goldfish",
      "quantity": 13,
      "_id": "522260b6f2f1e40000000004"
    }
  ]
}

I want to remove the goldfish with the sku of 12. I am doing the following:

var inventory = res.locals.content;
inventory.items.remove( {sku: req.params.itemSku}, function (err, item) {
  if (err) {
    console.log('error occurred', err);
    res.send('error');
  }
  else {
    res.send('Item found and deleted');
    return; 
  }
});

when I do this, I get the error "TypeError: Cannot read property 'equals' of undefined". I don't understand why.

Upvotes: 17

Views: 33881

Answers (8)

Aman Ghanghoriya
Aman Ghanghoriya

Reputation: 372

NOTE -

From mongoose 6.3.1 docs -

When executing a query with a callback function, you specify your query as a JSON document. The JSON document's syntax is the same as the MongoDB shell.

.

Upvotes: 0

Linus Gubenis
Linus Gubenis

Reputation: 11

You don't need the parent's _id. You can just search for a parent which has a child with a specific id and pull that same child out with the following code:

const result = await User.updateOne(
  // Query the user collection for a document
  // with a child in it's accounts array with an _id of ChildAccountId.
  { 'accounts._id': 'ChildAccountId' },
  {
    // In the found parent document:
    $pull: { // pull something out of:
      accounts: { // the accounts array 
        _id: 'ChildAccountId' // which has has the _id of ChildAccountId.
      }
    }
  }
);

result in this case will have a response-object similar to the following one:

{
  acknowledged: true,
  modifiedCount: 1,
  upsertedId: null,
  upsertedCount: 0,
  matchedCount: 1
}

So you can easily check for the result.modifiedCount to see how many SubDocuments (in this case) were modified (where stuff got pulled out).

Upvotes: 1

Alex
Alex

Reputation: 8663

Subdocuments now have a remove function. Use as follows from the spec:

var doc = parent.children.id(id).remove();
parent.save(function (err) {
  if (err) return handleError(err);
  console.log('the sub-doc was removed')
});

Upvotes: 32

danefondo
danefondo

Reputation: 555

Removing a subdocument from an array

The nicest and most complete solution I have found that both finds and removes a subdocument from an array is using Mongoose's $pull method:

Collection.findOneAndUpdate(
    { _id: yourCollectionId },
    { $pull: { subdocumentsArray: { _id: subdocumentId} } },
    { new: true },
    function(err) {
        if (err) { console.log(err) }
    }
)

The {new: true} ensures the updated version of the data is returned, rather than the old data.

Upvotes: 13

marquitobb
marquitobb

Reputation: 438

    const deleteitem = (req, res) => {
    var id = req.body.id
    var iditem = req.body.iditem

    Venta.findOne({'_id': id}, function(err,result){
        if (err) {
            console.log(err);            
        }else{
            result.items.pull(iditem)
            result.save()
        }
    })}
module.exports = {deleteitem }

Upvotes: 1

Syeda Aimen Batool
Syeda Aimen Batool

Reputation: 354

You can simply use $pull to remove a sub-document.

    Collection.update({
    _id: parentDocumentId
  }, {
    $pull: {
      subDocument: {
        _id: SubDocumentId
      }
    }
  });

This will find your parent document against given ID and then will remove the element from subDocument which matched the given criteria.

Upvotes: 2

Stan Smith
Stan Smith

Reputation: 111

finaly!

MongoDB:

"imgs" : {"other" : [ {
        "crop" : "../uploads/584251f58148e3150fa5c1a7/photo_2016-11-09_21-38-55.jpg",
        "origin" : "../uploads/584251f58148e3150fa5c1a7/o-photo_2016-11-09_21-38-55.jpg",
        "_id" : ObjectId("58433bdcf75adf27cb1e8608")
                                    }
                            ]
                    },
router.get('/obj/:id',  function(req, res) {
var id = req.params.id;



Model.findOne({'imgs.other._id': id}, function (err, result) {
        result.imgs.other.id(id).remove();
        result.save();            
    });

Upvotes: 7

Peter Lyons
Peter Lyons

Reputation: 145994

You want inventory.items.pull(req.params.itemSku), followed by an inventory.save call. .remove is for top-level documents

Upvotes: 19

Related Questions