Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose deleting (pull) a document within an array, does not work with ObjectID

I have the following mongoose schema:

user = {
    "userId" : "myId",
    "connections":
    [{
        "dateConnectedUnix": 1334567891,
        "isActive": true
    }, {
        "dateConnectedUnix": 1334567893,
        "isActive": false
    }]
}

I would like to delete the second item in the connections array, to get the following:

user = {
    "userId" : "myId",
    "connections": 
    [{
        "dateConnectedUnix": 1334567893,
        "isActive": false
    }]
}

The following code does the job as expected:

userAccounts.update(
    { 'connections.isActive': false }, 
    { $pull: { 'connections.isActive':false }}, 
    function (err, val) {
        console.log(val)
    }
);

But, I need to delete based on ObjectId. And the following goes does not work:

userAccounts.update(
    { 'connections._id': '1234-someId-6789' }, 
    { $pull: { 'connections._id': '1234-someId-6789' } },
    function (err, val) {
        console.log(val)
    }
);

Any suggestions? I have been banging my head against the screen (aka Google, Stackoverflow, ...) for hours and have had no luck.

like image 463
psiphi75 Avatar asked Nov 05 '13 09:11

psiphi75


People also ask

What is $pull in Mongoose?

$pull. The $pull operator removes from an existing array all instances of a value or values that match a specified condition.

What does .create do in Mongoose?

The `create()` Function in Mongoose. Mongoose models have a create() function that is often used to create new documents.

What is the difference between id and _ID in Mongoose?

From the documentation: Mongoose assigns each of your schemas an id virtual getter by default which returns the documents _id field cast to a string, or in the case of ObjectIds, its hexString.

What is __ V 0 in Mongoose?

The __v field is called the version key. It describes the internal revision of a document. This __v field is used to track the revisions of a document. By default, its value is zero.


7 Answers

It seems that the above code would not work. It should not even have worked for the first example I gave.

In the end I was supported by this answer here: MongoDB, remove object from array

Here is my working code:

userAccounts.update( 
    { userId: usr.userId },
    {
        $pull: {
            connections: { _id : connId }
        }
    },
    { safe: true },
    function removeConnectionsCB(err, obj) {
        // ...
    }
);
like image 94
psiphi75 Avatar answered Oct 04 '22 18:10

psiphi75


I have a document like

enter image description here

I have to delete address from address array

After searching lots on internet I found the solution

Customer.findOneAndUpdate(query, {$pull: {address: addressId}}, (err, data) => {
    if (err) {
        return res.status(500).json({ error: 'error in deleting address' });
    }
    res.json(data);   
});
like image 38
Deepak Sisodiya Avatar answered Oct 04 '22 19:10

Deepak Sisodiya


user: {
 _id: ObjectId('5ccf3fa47a8f8b12b0dce204'),
 name: 'Test',
 posts: [
  ObjectId("5cd07ee05c08f51af8d23b64"),
  ObjectId("5cd07ee05c08f51af8d23c52")
 ]
}

Remove a single post from posts array

user.posts.pull("5cd07ee05c08f51af8d23b64"); user.save();

like image 23
uak Avatar answered Oct 04 '22 18:10

uak


mongoose: 4.11.11
What have worked for me is the following syntax:

const removeTansactionFromUser = (userId, connectionId) => {
    return User.findByIdAndUpdate(userId, { $pull: { "connections": connectionId} }, {'new': true} );
};

Mongoose support id in string format or ObjectId format.
Tip: new ObjectId(stringId) to switch from string to ObjectId

like image 36
chenop Avatar answered Oct 04 '22 18:10

chenop


In mongoose 5.8.11, this $pull: { ... } didn't work for me, so far not sure why. So I overcame it in my controller this way:

exports.removePost = async (req, res, next) => {
  const postId = req.params.postId;
  try {
    const foundPost = await Post.findById(postId);
    const foundUser = await User.findById(req.userId);
    if (!foundPost || !foundUser) {
      const err = new Error(
        'Could not find post / user.',
      );
      err.statusCode = 404;
      throw err;
    }
    // delete post from posts collection:
    await Post.findByIdAndRemove(postId);
    // also delete that post from posts array of id's in user's collection:
    foundUser.posts.pull({ _id: postId });
    await foundUser.save();
    res.status(200).json({ message: 'Deleted post.' });
  } catch (err) {
    // ...
  }
};
like image 32
biscarrosse Avatar answered Oct 04 '22 18:10

biscarrosse


To use update with ObjectId, you should use ObjectId object instead of string representation :

var ObjectId = require('mongoose').Types.ObjectId;

userAccounts.update(
    { 'connections._id': new ObjectId('1234-someId-6789') }, 
    { $pull: { 'connections._id': new ObjectId('1234-someId-6789') } }, 
    function (err,val) {
        console.log(val)
    }
);
like image 32
throrin19 Avatar answered Oct 04 '22 19:10

throrin19


use findByIdAndUpdate to remove an item from an array

You can do it in mongoose 5.4.x and above

const result = await User.findByIdAndUpdate(user_id, {
    $pull: {
        someArrayName: { _id: array_item_id }
    }
}, { new: true });

if (result)
    console.log(result)

The item from array will be removed based on provided property _id value

like image 33
WasiF Avatar answered Oct 04 '22 20:10

WasiF