Suresh Pattu
Suresh Pattu

Reputation: 6209

Node js, Mongoose $and not working

I want to find a user where firstname and lastname matches.

router.post('/post/user/search/tag', function (req, res) {

function getRegex(_query) {
    return {
        $regex: '^' + _query + '|.*' + _query,
        $options: "i",
    };
}

var query = {};
query.$and = [];

_.map(req.body.params, function(_obj){
   query.$and[v.type] = getRegex(v.name);  
});

User.find(query).exec(function (err, docs) {
 res.json({err: false, data: docs});
});

});

Example input for this api is:

{"params":
  [
    {
      "name":"suresh",
      "type":"first_name"
    },
    {
      "name":"pattu",
      "type":"last_name"
    }
  ]
}

Error I am getting from mongoose is:

undefined { MongoError: $and/$or/$nor must be a nonempty array
    at Function.MongoError.create (/Users/user/code/project/trainer-ville-admin/node_modules/mongodb-core/lib/error.js:31:11)
    at queryCallback (/Users/user/code/project/trainer-ville-admin/node_modules/mongodb-core/lib/cursor.js:212:36)
    at /Users/user/code/project/trainer-ville-admin/node_modules/mongodb-core/lib/connection/pool.js:469:18
    at _combinedTickCallback (internal/process/next_tick.js:67:7)
    at process._tickCallback (internal/process/next_tick.js:98:9)
  name: 'MongoError',
  message: '$and/$or/$nor must be a nonempty array',
  ok: 0,
  errmsg: '$and/$or/$nor must be a nonempty array',
  code: 2,  codeName: 'BadValue' }

Input parsed on mongoose find query is:

{ '$and': 
   [ first_name:{ '$regex': '^suresh|.*suresh', '$options': 'i' },
     last_name:{ '$regex': '^pattu|.*pattu', '$options': 'i' }
   ] 
}

Upvotes: 0

Views: 734

Answers (2)

Juan
Juan

Reputation: 6383

Your issue is in this lines:

_.map(function(_obj){
   query.$and[v.type] = getRegex(v.name);  
});

You are calling _.map which iterates through a collection but there's no collection there. It should look something like this:

_.map(someCollection, function(_obj) {
   query.$and[v.type] = getRegex(v.name);  
});

You are not iterating through anything in your code, so query.$and[v.type] = getRegex(v.name); is never executed, so your $and array is empty.

Also, I don't see where v is being defined in your snippet.

Here is some useful links on how _.map works and what params it receives:

.map in lodash .map in underscore

Hope this is of help.

Upvotes: 0

Neil Lunn
Neil Lunn

Reputation: 151072

You actually do not need $and since all MongoDB query arguments are already AND conditions:

Do this instead:

var input = {
    "params" : [
            {
                    "name" : "suresh",
                    "type" : "first_name"
            },
            {
                    "name" : "pattu",
                    "type" : "last_name"
            }
    ]
};



var query = { };
input.params.forEach(p => {
  query[p.type] = new RegExp('^'+ p.name + '|.*' + p.name, 'i');
})

The output in query looks like:

{ "first_name" : /^suresh|.*suresh/i, "last_name" : /^pattu|.*pattu/i }

Which is of course the perfectly valid statement you want.

See also $regex which also accepts RegExp generated objects in a JavaScript environment.

Upvotes: 1

Related Questions