如何使用 mongodb 架构实现自定义过滤器?
How to implement a custom filter with mongodb schema?
我想知道是否可以实施任何方法来为复杂搜索设置自定义过滤器?
例如,
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;
})
像这样。我知道我可以 await User.find({}) 并在其上使用数组过滤方法进行过滤,但我担心的是,在那种情况下,我将无法进行我可以用 mongoose 进行的分页limit(), skip() 方法。
如有任何帮助,我们将不胜感激。谢谢!
编辑:刚刚发现可以使用带有 $redact 的聚合来实现此目的,但仍未弄清楚如何实现它来满足此需求。
您可以使用 $switch 聚合框架运算符。
https://docs.mongodb.com/manual/reference/operator/aggregation/switch/#example
根据您的要求,这里有一个例子
示例文档
每个案例一份文件
{
"name" : "sensor1",
"measure" : "C",
"value" : 36
}
{
"name" : "sensor2",
"measure" : "F",
"value" : 78
}
{
"name" : "sensor3",
"measure" : "C",
"value" : 12
}
{
"name" : "sensor4",
"measure" : "F",
"value" : 113
}
查询
使用不同的案例,您可以根据度量和值涵盖所有场景。
- 在大小写运算符中设置了华氏度公式。
- 如果需要,添加您的排序运算符和其他匹配条件。
$skip
和 $limit
可以使用代码动态设置
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}])
结果
{
"name" : "sensor1",
"measure" : "C",
"value" : 36,
"result" : true
}
{
"name" : "sensor2",
"measure" : "F",
"value" : 78,
"result" : false
}
我想知道是否可以实施任何方法来为复杂搜索设置自定义过滤器?
例如,
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;
})
像这样。我知道我可以 await User.find({}) 并在其上使用数组过滤方法进行过滤,但我担心的是,在那种情况下,我将无法进行我可以用 mongoose 进行的分页limit(), skip() 方法。
如有任何帮助,我们将不胜感激。谢谢!
编辑:刚刚发现可以使用带有 $redact 的聚合来实现此目的,但仍未弄清楚如何实现它来满足此需求。
您可以使用 $switch 聚合框架运算符。
https://docs.mongodb.com/manual/reference/operator/aggregation/switch/#example
根据您的要求,这里有一个例子
示例文档
每个案例一份文件
{
"name" : "sensor1",
"measure" : "C",
"value" : 36
}
{
"name" : "sensor2",
"measure" : "F",
"value" : 78
}
{
"name" : "sensor3",
"measure" : "C",
"value" : 12
}
{
"name" : "sensor4",
"measure" : "F",
"value" : 113
}
查询
使用不同的案例,您可以根据度量和值涵盖所有场景。
- 在大小写运算符中设置了华氏度公式。
- 如果需要,添加您的排序运算符和其他匹配条件。
$skip
和$limit
可以使用代码动态设置
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}])
结果
{
"name" : "sensor1",
"measure" : "C",
"value" : 36,
"result" : true
}
{
"name" : "sensor2",
"measure" : "F",
"value" : 78,
"result" : false
}