Home > OS >  How to implement a custom filter with mongodb schema?
How to implement a custom filter with mongodb schema?

Time:09-28

I need to know is there any method that I can implement to have a custom filter for a complex search?

For example,

User.someMethodName((eachUser) => {
   const temp = eachUser.temperature;
   if(temp.mesure === 'C' && temp.value > 36) return true;
   if(temp.mesure === 'F' && convertToCel(temp.value) > 36) return true;
   return false;
})

something like this. I know that I can await User.find({}) and use the array filter method on it to filter but my concern is that in that case, I wouldn't be able to do my pagination which I can do with mongoose limit(), skip() methods.

Any help would be highly appreciated. Thanks!

Edit: Just found out can use aggregate with $redact to achieve this, but still not figured out how exactly implement it to meet this need.

CodePudding user response:

You can use the $switch aggregate framework operator.

https://docs.mongodb.com/manual/reference/operator/aggregation/switch/#example

Here an example based on your requirements

Sample documents

One document per case

{
  "name" : "sensor1",
  "measure" : "C",
  "value" : 36 
}

{
  "name" : "sensor2",
  "measure" : "F",
  "value" : 78
}

{
  "name" : "sensor3",
  "measure" : "C",
  "value" : 12
}

{
  "name" : "sensor4",
  "measure" : "F",
  "value" : 113
}

Query

Using different cases you can cover all scenario based on the measure and the value.


  • Fahrenheit formula is set inside the case operator.
  • Add your sort operator and other match conditions if you need.
  • $skip and $limit can be set dynamically using code

db.test.aggregate(
[{$project : { 
 "name" : 1, 
 "measure": 1,
 "value": 1,
 "result" :
 { $switch:
    {
       branches: [
          { 
          //when your Celsius temp is greater and equals to 36
          case: { $and : [ { $eq : [ "$measure" , "C" ] },
                           { $gte : [ "$value" , 36 ] } ] },
          then: true    
          },
          { 
          //when your Celsius temp is less then 36
          case: { $and : [ { $eq : [ "$measure" , "C" ] },
                           { $lt : [ "$value" , 36 ] } ] },
          then: false
          },
          { 
          //when your Fahrenheit temp is greater and equals to 36
          case: { $and : [ { $eq : [ "$measure" , "F" ] },
                            { $gte : [ {"$multiply" : [ { "$sum": 
                                       ["$value", -32]}, 5/9]} , 36 ] } ] },
          },
          then: true    
          },
          { 
          //when your Fahrenheit temp is less than 36
          case: { $and : [ { $eq : [ "$measure" , "F" ] },
                           { $lt  : [ {"$multiply" : [ { "$sum": 
                                    ["$value", -32]}, 5/9]} , 36 ] } ] }, ] },
          then: false    
          }
       ],
       default: "error"
    }
}}},
{$skip : 0},
{$limit : 2}])

Result

{
  "name" : "sensor1",
  "measure" : "C",
  "value" : 36,
  "result" : true
}
{
  "name" : "sensor2",
  "measure" : "F",
  "value" : 78,
  "result" : false
}
  • Related