Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding mongoose findOne().remove()

As you know, in mongoose, we can remove all users with age 30 like this:

User.find({age: 30}).remove(callback);

Now, replace find() with findOne(), and I think it should remove only 1 user:

User.findOne({age: 30}).remove(callback);

oh, not as I expected, the code above also remove ALL instead of ONE

So, why findOne().remove() remove ALL instead of ONE? Is that a bug or a feature and why?

Thanks in advance!

P/S: I know findOneAndRemove() would remove one user for me, but in this question I want to understand findOne().remove()

like image 386
damphat Avatar asked Dec 29 '13 07:12

damphat


People also ask

How does a Mongoose findOne work?

Mongoose | findOne() Function The findOne() function is used to find one document according to the condition. If multiple documents match the condition, then it returns the first document satisfying the condition.

What does findOne return Mongoose?

Mongoose findOne query returns a query object, not a document. You can either use a callback as the solution suggests or as of v4+ findOne returns a thenable so you can use . then or await/async to retrieve the document.

How do you delete an item from MongoDB using Mongoose?

There is currently no method called deleteById() in mongoose. However, there is the deleteOne() method with takes a parameter, filter , which indicates which document to delete. Simply pass the _id as the filter and the document will be deleted.

How do I delete all Mongoose?

Mongoose | deleteMany() Function The deleteMany() function is used to delete all of the documents that match conditions from the collection. This function behaves like the remove() function but it deletes all documents that match conditions regardless of the single option.


2 Answers

I have reported this question to mongoose team, and got a reply:

https://github.com/LearnBoost/mongoose/issues/1851#issuecomment-31355346

Here's the message from aheckmann

"that's a good catch. findOne just sets the command name to run, remove() changes it back to a rice command but no limit was ever set. We should probably change that in 3.9 so that findOne sets the limit as well."

like image 199
damphat Avatar answered Oct 22 '22 07:10

damphat


Both find and findOne returns mongoose Query objects which only contains information about the model and the specified query. It's not taking into account findOne which is applied first in the callback. What you expect to happen is to have options be set like this User.findOne({age: 30}, null, {limit: 1}).remove() as this would only remove one and you could argue that this is a bug, but that depends on the usage. Like you have already pointed out, the right way to go is to use findOneAndRemove().

like image 40
Mattias Farnemyhr Avatar answered Oct 22 '22 06:10

Mattias Farnemyhr