Runny Yolk Runny Yolk - 1 month ago 13
Node.js Question

Dynamic Query MongoDB

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?

Answer

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:

  1. https://docs.mongodb.com/manual/reference/operator/query/and/
  2. https://docs.mongodb.com/manual/reference/operator/query/in/

And here's a working jsbin you can play with:

  1. http://jsbin.com/cequbipiso/edit?js,console