MongoDB 聚合 $project 和 $match

MongDB Aggregation with $project and $match

我有类似的文档:

 {_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' 和 '$duration'。当我将第二个匹配项中的 'duration' 替换为硬编码数值(如 0)时,查询会按预期工作(通过过滤掉值不大于或等于 0 的文档)。

[
{$match: {_id: {$ne: ObjectId('98765')}}},
{$project: { duration:{$subtract:[Date.now(),'$timestamp']}, value:1, _id:1}},
{$match:{value:{$gte:0}}}
]

似乎可能存在一些 "types" 问题 mongo 正在默默地忽略并且不返回任何东西...有人可以指出我在上述聚合方法中可能遗漏的内容???谢谢!!

$match aggregation stage does not work like that. Just like standard queries you cannot reference the value of a field to a query operator against another field. There are logical operators for comparison and they are used with stages like $project,像这样:

{ "$project": { 
    "duration":{ "$subtract":[ Date.now(),"$timestamp"]}, 
    "value":1, 
    "matched": { "$gte": [ "$value", { "$subtract":[ Date.now(),"$timestamp"]} ] }
}},
{ "$match": { "matched": true } }

但实际上 $redact 和 "optionally" 投影您的新字段可能更好:

{ "$redact": {
    "$cond": {
        "if": {  "$gte": [ "$value", { "$subtract":[ Date.now(),"$timestamp"]} ] },
        "then": "$$KEEP",
        "else": "$$PRUNE"
    }
}},
{ "$project": { 
    "duration": { "$subtract":[ Date.now(),"$timestamp"] }, 
    "value":1
}},

所以 $redact 以 "logical" 的方式工作,与 $match 以 "physical" 的方式工作相同,并且可以包含可以计算值的表达式或直接在文档上进行字段比较以 "filter" 内容。

这样做基本上也很方便,因为 $project 的成本实际上只限于那些满足条件的文档,如果您甚至需要输出中的计算值, 在这种情况下你可以完全跳过它。

您在第二次匹配查询中犯了一个简单的错误。

 {$match:{value:{$gte:'duration'}}}

应该是:

{$match:{value:{$gte:'$duration'}}}

duration”是聚合管道第二阶段生成的变量。所以它应该在第三阶段被称为'$duration'。