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
}