我的文件类似于:
{_id:'12345', timestamp:41123412451, value:1000}
{_id:'98765', timestamp:41123498714, value:2000}
{_id:'11122', timestamp:41287364245, value:3000}
我正在运行类似于以下的聚合查询:
[
{$match: {_id: {$ne: ObjectId('98765')}}},
{$project: { duration:{$subtract:[Date.now(),'$timestamp']}, value:1, _id:1}},
{$match:{value:{$gte:'duration'}}}
]
当我删除第二场$ match时,我会收到所有文件,除了' 98765' (如预期的那样)。但是,当我加入第二场$ match时,我没有得到任何文件。我试过了#duration;#39;和' $ duration'。当我更换'持续时间'在第二次匹配中,硬编码数字值为0,查询按预期工作(通过过滤掉值不大于或等于0的文档)。
[
{$match: {_id: {$ne: ObjectId('98765')}}},
{$project: { duration:{$subtract:[Date.now(),'$timestamp']}, value:1, _id:1}},
{$match:{value:{$gte:0}}}
]
似乎可能有一些"类型" mongo的问题是默默地忽略并且没有返回任何东西......有人可以通过上述聚合方法指出我可能缺少的东西吗?谢谢!
答案 0 :(得分:2)
$match
聚合阶段不起作用。就像标准查询一样,您无法将字段的值引用到查询运算符而不是另一个字段。有logical operators for comparison,它们与$project
等阶段一起使用,如下所示:
{ "$project": {
"duration":{ "$subtract":[ Date.now(),"$timestamp"]},
"value":1,
"matched": { "$gte": [ "$value", { "$subtract":[ Date.now(),"$timestamp"]} ] }
}},
{ "$match": { "matched": true } }
但实际上,$redact
和“可选地”投射新字段可能会更好:
{ "$redact": {
"$cond": {
"if": { "$gte": [ "$value", { "$subtract":[ Date.now(),"$timestamp"]} ] },
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
{ "$project": {
"duration": { "$subtract":[ Date.now(),"$timestamp"] },
"value":1
}},
所以$redact
以“逻辑”的方式工作,与$match
以“物理”方式工作的方式相同,并且可以包含可以对其进行计算值或直接字段比较的表达式文档以“过滤”内容。
通过这样做,基本上也很方便,因为$project
的成本实际上仅限于满足条件的那些文档,如果你甚至需要输出中的计算值,那么在哪种情况下你可以完全跳过它。
答案 1 :(得分:0)
你在第二场比赛中犯了一个简单的错误。
{$match:{value:{$gte:'duration'}}}
应该是:
{$match:{value:{$gte:'$duration'}}}
'持续时间'是由聚合管道的第二阶段生成的变量。因此,它应在第3阶段称为“ $ duration ”。