简体   繁体   中英

MongoDB/Mongoose Query Builder

I am trying to build a query builder which will allow me to filter the data based on the parameters entered by user. My Data Model is like so:

{
"_id": {
    "$oid": "871287215784812"
},
"tags": [
    "school",
    "book",
    "bag",
    "headphone",
    "appliance"
],

"consultingDays": 57,
"client": "someOne",
"subSector": "something",
"region": "UK",
"__v": 0
}

Currently my Query Builder looks like this:

app.post('/user/test',function(req, res) {

var query = {};

//QUERY NO.1 - This works perfectly
if (req.body.region){
    query.region = req.body.region
    console.log(query.region)
}

// QUERY NO.2 - This works perfectly  
if (req.body.subSector){
    query.subSector = req.body.subSector
}

Project.find(query, function(err, project){
    if (err){
        res.send(err);
    }
    console.log(project);
    res.json(project);
});
});

My Question:

I want to create a query which will take input from user and parse the "tags" array and return the required JSON.

For example:

If the user requests an object which contains "school", "book", "bag" it will return the object as seen my data model above. But if the user requests an object with "school", "book", "ninja Warrior" it won't return any data as no object within the database contain all those 3 strings.

What I have tried:

I have tried the following

if (req.body.sol){
    query.solutions = {"tags" : {$in: [req.body.sol]}} 
}

OR

if (req.body.sol){
    query.solutions = {$elemMatch:{tags: req.body.sol}}
}

OR

 if (req.body.sol){
    query.solutions = { tags: { $all: [req.body.sol]}}
}

The requests were sent like so and they returned an empty array:

在此处输入图片说明

Also the issue is that the user will get dropdown options. For example he/she might get 3 dropdown boxes. Each dropdown box will display all the five options in the tags array. The user will select a value for each dropdown box. And then filter the result. Because there might be an object within the database that contains "book", "bag", "shoes" within the tags array. The user can select any combination of those five keywords in the tags array

Does anyone know how I can fix this?

You need to send an array as sol so in Postman you should change sol with sol[0] , sol[1] , etc.. Then use this:

if (req.body.sol){
    query.solutions = {"tags" : {$in: req.body.sol}} 
}

Without the [] because req.body.sol is an array yet.

I have implemented a simple query build for nested objects:

const checkObject = (object) => {
  let key;

  const status = Object.entries(object).some(([objectKey, objectValue]) => {
    if (typeof objectValue === "object" && objectValue !== null) {
      key = objectKey;

      return true;
    }

    return false;
  });

  return { status, key };
};

const queryBuilder = (input) => {
  // Array verification not implemented
  let output = {};

  _.each(input, (value, key) => {
    if (typeof value === "object" && value !== null) {
      _.each(value, (nestedValue, nestedKey) => {
        output[`${[key, nestedKey].join(".")}`] = nestedValue;
      });
    } else {
      output[key] = value;
    }
  });

  const cacheCheckObject = checkObject(output);

  if (cacheCheckObject.status)
    return { ..._.omit(output, cacheCheckObject.key), ...queryBuilder(output) };

  return output;
};

I have not implemented array, but with some small work you can do it work. The same for Mongo operators. The complete example can be seen on Gist .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM