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'。
我有类似的文档:
{_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'。