MongoDB 聚合管道:$match 与表达式不可能?

nar*_*esh 4 mongodb aggregation-framework

我正在做一个相当复杂的聚合管道并且有一个相当奇怪的现象 - 我在这里提取了一个简短的例子来形象化我的问题。

它似乎与MongoDb $addFields 和 $match 相关- 但它不包含任何信息供我解决手头的问题。

注意:请注意,我的问题不在于使用日期字段和/或处理值的具体示例,问题在于我无法$match使用表达式 - 使用之前添加的字段$addFields。

鉴于 MongoDB:3.6.3(目前最新)

让我们插入一些测试数据:

db.testexample.insert({
   "dateField": new ISODate("2016-05-18T16:00:00Z")
});

db.testexample.insert({
   "dateField": new ISODate("2018-05-18T16:00:00Z")
});
Run Code Online (Sandbox Code Playgroud)

现在让我们制作一个简单的管道,只计算日期的年份和 $matches:

db.testexample.aggregate([
    {
        "$addFields": {
            "dateFieldYear": {"$year": "$dateField"}
        }
    },
    {
        "$match": {
            "dateFieldYear": {"$eq": "$dateFieldYear"}}
        }
    }
])
Run Code Online (Sandbox Code Playgroud)

--> 没有匹配项

它应该匹配,因为它是同一个领域?也许有更多技巧(使用$add)?

db.testexample.aggregate([
    {
        "$addFields": {
            "dateFieldYear": {"$year": "$dateField"}
        }
    },
    {
        "$match": {
            "dateFieldYear": {"$eq": {"$add": ["$dateFieldYear", 0]}}
        }
    }
])
Run Code Online (Sandbox Code Playgroud)

--> 没有匹配项

仍然没有骰子......接下来我认为变量完全是一个问题。所以让我们修正这些值:

db.testexample.aggregate([
    {
        "$addFields": {
            "dateFieldYear": {"$year": "$dateField"}
        }
    },
    {
        "$match": {
            "dateFieldYear": {"$eq": {"$add": [2016, 0]}}
        }
    }
])
Run Code Online (Sandbox Code Playgroud)

--> 没有匹配项

等等..这里真的有问题..让我们看看静态值:

db.testexample.aggregate([
    {
        "$addFields": {
            "dateFieldYear": {"$year": "$dateField"}
        }
    },
    {
        "$match": {
            "dateFieldYear": 2016
        }
    }
])
Run Code Online (Sandbox Code Playgroud)

--> 找到 1 条记录!

所以我的结论似乎是$match不能对聚合管道中的字段进行表达式。但这似乎不可能 - 因为文档声明$match遵循此处描述的查询语法。

任何人都可以帮助如何$match使用简单的示例来完成它"dateFieldYear": {"$eq": "$dateFieldYear"}}- 为什么这不能按预期工作?

非常感谢您的帮助

use*_*814 6

您可以使用$expr( 3.6 mongo version operator ) 在常规查询中使用聚合函数。

比较query operatorsvs aggregation comparison operators。

在你的情况下

db.testexample.find({$expr:{$eq:["$dateFieldYear", "$dateFieldYear"]}})
Run Code Online (Sandbox Code Playgroud)

常规查询:

db.testexample.find({$expr:{$eq:["$dateFieldYear", {"$year": "$dateField"}]}})
Run Code Online (Sandbox Code Playgroud)

聚合查询:

db.testexample.aggregate({$match:{$expr:{$eq:["$dateFieldYear", {"$year": "$dateField"}]}})
Run Code Online (Sandbox Code Playgroud)