I'm trying to build a MongoDB query object based on data received from a client-side search form. My goal is to query the database with any and all criteria provided by the user, whilst allowing the user to leave some search fields blank if they choose to.
This is my current attempt at a query object is:
var q = {}; // declare the query object
q['$and']=[]; // filter the search by any criteria given by the user
if((req.body.learninglanguages).length > 0){ // if the criteria has a value or values
q["$and"].push('{learningLanguages: {$in: ' + req.body.learninglanguages.split(",") + '}}'); // add to the query object
}
if((req.body.spokenlanguages).length > 0){
q["$and"].push('{spokenLanguages: {$in: ' + req.body.spokenlanguages.split(",") + '}}');
}
if((req.body.country).length > 0){
q["$and"].push('{country: {$in: ' + req.body.country.split(",") + '}}');
}
if((req.body.commethod).length > 0){
q["$and"].push('{comMethod: {$in: ' + req.body.commethod.split(",") + '}}');
}
But the resulting object is:
{ '$and':
[ '{learningLanguages: {$in: Albanian,American Sign Language,Amharic,Arabic,Arabic (Egyptian)}}',
'{spokenLanguages: {$in: Akan,Albanian,American Sign Language,Amharic}}',
'{country: {$in: Åland Islands}}',
'{comMethod: {$in: whatsapp,email,face to face,skype}}' ] }
How can I correctly build a MongoDB $in query from req.body objects?
The problem with your query is you are attempting to build a string instead of directly building an object, like mongoDB & mongoose accept:
var q = {}; // declare the query object
q['$and']=[]; // filter the search by any criteria given by the user
if((req.body.learninglanguages).length > 0){ // if the criteria has a value or values
q["$and"].push({ learningLanguages: {$in: req.body.learninglanguages.split(",") }}); // add to the query object
}
if((req.body.spokenlanguages).length > 0){
q["$and"].push({ spokenLanguages: {$in: req.body.spokenlanguages.split(",") }});
}
if((req.body.country).length > 0){
q["$and"].push({ country: {$in: req.body.country.split(",") }});
}
if((req.body.commethod).length > 0){
q["$and"].push({ comMethod: {$in: req.body.commethod.split(",") }});
}
You can see that instead of pushing in a string, I am instead pushing in a direct object that fits the documentation specifications.
See the documentation here for more information:
And here's a working jsbin
you can play with:
I followed Derek's suggestion, which is spot on in terms of how to dynamically construct the query conditions. But it appears that this code does not handle a scenario where no search parameters are specified.
Specifically, if all req.body parameters are empty, then you have a query object with an empty $and array as declared here:
q['$and']=[];
This results in a MongoError: $and/$or/$nor must be a nonempty array
error.
Here's what I did to fix this issue:
var conditions = {}; //declare a conditions object
var and_clauses = []; //an array for the and conditions (and one for or conditions and so on)
if((!!req.body.email_id)){
and_clauses.push({ 'email_id': {$regex: req.body.email_id }});
}
if(and_clauses.length > 0){
conditions['$and'] = and_clauses; // filter the search by any criteria given by the user
}
//Run the query
User.find(conditions,
function(err, users) {
if (err){
console.log(err);
res.status(500).send(err);
}else{
console.log(users);
res.status(200).json(users);
}
});
Derek, apologies if I got something wrong, don't want to point out an issue incorrectly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With