goosetapa
goosetapa

Reputation: 5047

Mongoose's find method with $or condition does not work properly

Recently I start using MongoDB with Mongoose on Nodejs.

When I use Model.find method with $or condition and _id field, Mongoose does not work properly.

This does not work:

User.find({
  $or: [
    { '_id': param },
    { 'name': param },
    { 'nickname': param }
  ]
}, function(err, docs) {
   if(!err) res.send(docs);
});

By the way, if I remove the '_id' part, this DOES work!

User.find({
  $or: [
    { 'name': param },
    { 'nickname': param }
  ]
}, function(err, docs) {
   if(!err) res.send(docs);
});

And in MongoDB shell, both work properly.

Upvotes: 170

Views: 248662

Answers (5)

K Sanketh kumar
K Sanketh kumar

Reputation: 9

router.get("/filter", async (req, res) => {
  const filter = req.query.filter || "";
  const users = await User.find({
    $or: [{ firstName: { $regex: filter } }, { lastName: { $regex: filter } }],
  });
  res.json({
    users: users
  });
});

Upvotes: -1

Nigam Sharma
Nigam Sharma

Reputation: 1

router.get("/bulk", async (req, res) => {
    const filter = req.query.filter || "";

    const users = await User.find({
        $or: [
                {
                   firstName: { "$regex": filter }
                },
                {
                   lastName: { "$regex": filter }
                }
             ]
    })

    res.json({
        user: users.map(user => ({
            username: user.username,
            firstName: user.firstName,
            lastName: user.lastName,
            _id: user._id
        }))
    })
})

Upvotes: -2

AllJs
AllJs

Reputation: 1810

You can also add a mix of $or and and to give your functions more flexibility, options and robustness, like so:

var ObjectId = require("mongoose").Types.ObjectId;
var idParam = new ObjectId(param.length < 12 ? "123456789012" : param);
const {nameParam, nicknameParam, ageParam} = req.params || req.body || req.query

User.find({
        $or: [{
                _id: objId
            },
            {
                name: nameParam
            },
            {
                nickname: nicknameParam
            }
        ],
        $and: [{
            age: ageParam
        }]
    },
    function (err, docs) {
        if (!err) res.send(docs);
    }
);

So this means that your find() will look for all users where (_id = idParam OR name = nameParam OR nickname = nicknameParam) AND (age = ageParam)

I hope this helps someone out there. Cheers!!!

Upvotes: 7

Govind Rai
Govind Rai

Reputation: 15780

I implore everyone to use Mongoose's query builder language and promises instead of callbacks:

User.find().or([{ name: param }, { nickname: param }])
    .then(users => { /*logic here*/ })
    .catch(error => { /*error logic here*/ })

Read more about Mongoose Queries.

Upvotes: 93

goosetapa
goosetapa

Reputation: 5047

I solved it through googling:

var ObjectId = require('mongoose').Types.ObjectId;
var objId = new ObjectId( (param.length < 12) ? "123456789012" : param );
// You should make string 'param' as ObjectId type. To avoid exception, 
// the 'param' must consist of more than 12 characters.

User.find( { $or:[ {'_id':objId}, {'name':param}, {'nickname':param} ]}, 
  function(err,docs){
    if(!err) res.send(docs);
});

Upvotes: 295

Related Questions