Michael
Michael

Reputation: 16142

Check if ID exists in a collection with mongoose

For instance, I have a collection User:

var mongoose = require('mongoose');

var UserSchema = new mongoose.Schema({
    email: String,
    googleId: String,
    facebookId: String,
    displayName: String,
    active: Boolean
});

module.exports = mongoose.model('User', UserSchema);

And then I have an ID:

var userID = "some-user-id"

What is the right way to just check if this id exists in the User collection. I don't need it to read the file or return it, I just need the true or false value.

Here is one way to achieve it:

User.findOne({
     _id: userID
}, function (err, existingUser) {

But is there faster and more efficient way?

Upvotes: 54

Views: 95698

Answers (6)

svrznjak
svrznjak

Reputation: 91

The accepted answer is excellent, but I would really recommend using estimatedDocumentCount() if you are searching existing document by an indexed property (like _id of X).

On the other hand, this should actually work better and is cleaner.

Upvotes: 0

Alex
Alex

Reputation: 38519

Use count rather than findOne.

This will (under the hood) cause mongoose to use find : http://docs.mongodb.org/manual/reference/method/db.collection.count

findOne() will read + return the document if it exists On the other hand, find() just returns a cursor (or not) and only reads the data if you iterate over the cursor. So in our case, we're not iterating over the cursor, merely counting the results returned.

User.countDocuments({_id: userID}, function (err, count){ 
    if(count>0){
        //document exists });
    }
}); 

Upvotes: 82

Shriya Madan
Shriya Madan

Reputation: 171

OR you can simply use exists function, without making any async/await:

myData = {_id: userID};

User.exists(myData,(error, result)=>{
    if (error){
      console.log(error)
    } else {
      console.log("result:", result)  //result is true if myData already exists
    }
  });

You can play with the result now!

Upvotes: 4

Hasan Sefa Ozalp
Hasan Sefa Ozalp

Reputation: 7208

User.exists({ _id: userID }).then(exists => {
  if (exists) {
    res.redirect('/dashboard')
  } else {
    res.redirect('/login')
  }
})

More info can be found at Mongoose docs.

Upvotes: 0

Tom
Tom

Reputation: 5121

You can now use User.exists() as of September 2019 like so:

const doesUserExit = await User.exists({ _id: userID });

From the docs:

Under the hood, MyModel.exists({ answer: 42 }) is equivalent to MyModel.findOne({ answer: 42 }).select({ _id: 1 }).lean().then(doc => !!doc)

Upvotes: 77

Alisson Reinaldo Silva
Alisson Reinaldo Silva

Reputation: 10695

The accepted answer is fine for small collections.

A faster way on larger collections is to simply use this:

const result = await User.findOne({ _id: userID }).select("_id").lean();
if (result) {
    // user exists...
}

// or without "async/await":

User.findOne({ _id: userID }).select("_id").lean().then(result => {
    if (result) {
        // user exists...
    }
});

It won't return all fields. I believe they are currently working on a new feature to support what you (and I) want.


In the meantime you could create a plugin, very simple and reusable.

Create an any.js file with this code:

module.exports = function any(schema, options) {
    schema.statics.any = async function (query) {
        const result = await this.findOne(query).select("_id").lean();
        return result ? true : false;
      };
  }

Then in your model you do this:

var mongoose = require('mongoose');
const any = require('./plugins/any'); // I'm assuming you created a "plugins" folder for it

var UserSchema = new mongoose.Schema({
    email: String,
    googleId: String,
    facebookId: String,
    displayName: String,
    active: Boolean
});

UserSchema.plugin(any);
module.exports = mongoose.model('User', UserSchema);

...and use it like this:

const result = await User.any({ _id: userID });
if (result) {
    // user exists...
}

// or without using "async/await":

User.any({ _id: userID }).then(result => {
    if (result) {
        // user exists...
    }
});

Upvotes: 13

Related Questions