使用$ eq运算符时,无法在case语句中引用MongoDB文档字段

时间:2018-03-01 05:58:40

标签: mongodb mongodb-query aggregation-framework

我的MongoDB版本是3.6.3

我收藏的一个例子:

/*A snippet of my collection*/
/* 1 */
{
    "_id" : ObjectId("5a81a0de19a4ea2a8b119baa"),
    "Site" : 123,
    "Event" : "AnEvent",
    "SubEvent" : "MoreDetails",
    "Level" : 2
}

/* 2 */
{
    "_id" : ObjectId("5a81a0de19a4ea2a8b119bab"),
    "Site" : 456,
    "Event" : "TheEvent",
    "SubEvent" : "FurtherDetails",
    "Level" : 3
}

/* 3 */
{
    "_id" : ObjectId("5a81a0de19a4ea2a8b119bac"),
    "Site" : 789,
    "Event" : "WorldEndingEvent",
    "SubEvent" : "RelevantDetails",
    "Level" : 5
}

我正在尝试输出以下文档(根据Event和SubEvent字段有条件地添加新字段):

/*Desired output of query*/
/* 1 */
{
    "_id" : ObjectId("5a81a0de19a4ea2a8b119baa"),
    "Site" : 123,
    "Event" : "AnEvent",
    "SubEvent" : "MoreDetails",
    "Level" : 2,
    "NewLevel": 1
}

/* 2 */
{
    "_id" : ObjectId("5a81a0de19a4ea2a8b119bab"),
    "Site" : 456,
    "Event" : "TheEvent",
    "SubEvent" : "FurtherDetails",
    "Level" : 3,
    "NewLevel": 2
}

/* 3 */
{
    "_id" : ObjectId("5a81a0de19a4ea2a8b119bac"),
    "Site" : 789,
    "Event" : "WorldEndingEvent",
    "SubEvent" : "RelevantDetails",
    "Level" : 5,
    "NewLevel": 4
}

为实现这一目标,我使用的是MongoDB提供的switch case结构(但没有成功):

/*This does not work as Mongo does not recognize $Event in case statement*/
db.getCollection('Error_events_aggregated').aggregate([
    {
        $project: {
            Site: 1,
            Event: 1,
            SubEvent: 1,
            Level: 1,
            NewLevel: {
                $switch: {
                    branches: [
                        {
                            case: {$and: [
                                          {"$Event": {$eq: "AnEvent"}},
                                          {"$SubEvent": {$eq: "MoreDetails"}}
                                          ]},
                            then: 1
                        },
                        {
                            case: {$and: [
                                          {"$Event": {$eq: "TheEvent"}},
                                          {"$SubEvent": {$eq: "FurtherDetails"}}
                                          ]},
                            then: 2
                        },
                        {
                            case: {$and: [
                                          {"$Event": {$eq: "WorldEndingEvent"}},
                                          {"$SubEvent": {$eq: "RelevantDetails"}}
                                          ]},
                            then: 4
                        }
                    ],
                    default: "$Level"
                    }
                }
            }
        }
])

这不起作用,因为MongoDB无法识别$ Event。

但是,如果我使用类似的方法(基于开关案例的投影)但使用$ gt(和类似的)运算符,那么MongoDB在识别$ Event时没有任何问题......

/*This works. Mongo recognizes $Event now, inside the case statement*/
db.getCollection('Error_events_aggregated').aggregate([
    {
        $project: {
            Site: 1,
            Event: 1,
            SubEvent: 1,
            Level: 1,
            NewLevel: {
                $switch: {
                    branches: [
                        {
                            case: {$gt: ["$Event", "V"]}, /*Matches WorldEndingEvent*/
                            then: 4 
                        },
                        {
                            case: {$gt: ["$Event", "S"]}, /*Matches TheEvent*/
                            then: 2
                        },
                        {
                            case: {$gt: ["$Event", "Am"]}, /*Matches AnEvent*/
                            then: 1
                        }
                    ],
                    default: "$Level"
                    }
                }
            }
        }
])

有人可以帮我弄清楚我做错了什么吗?我尝试阅读文档,但所有与$ switch和$ cond相关的示例仅涵盖$ gt和类似的运算符,并不涵盖基于平等的操作。

我尝试使用{:}语法来检查相等性,但无济于事。

2 个答案:

答案 0 :(得分:3)

您可以使用$addFields代替$project$switch$eq的语法在这里完全不同,请尝试:

db.col.aggregate([
    {
        $addFields: {
            NewLevel: {
                $switch: {
                    branches: [
                        {
                            case: {
                                $and: [
                                    { $eq: [ "$Event", "AnEvent" ] },
                                    { $eq: [ "$SubEvent", "MoreDetails" ] }
                                ] 
                            },
                            then: 1
                        },
                        {
                            case: {
                                $and: [
                                    { $eq: [ "$Event", "TheEvent" ] },
                                    { $eq: [ "$SubEvent", "FurtherDetails" ] }
                                ] 
                            },
                            then: 2
                        },
                        {
                            case: {
                                $and: [
                                    { $eq: [ "$Event", "WorldEndingEvent" ] },
                                    { $eq: [ "$SubEvent", "RelevantDetails" ] }
                                ] 
                            },
                            then: 4
                        }
                    ],
                    default: "$Level"
                }
            }
        }
    }
])

答案 1 :(得分:2)

mongoDB中的switch语句基本上是对一系列案例EXPRESSIONS进行评估,因此case语句中包含的任何内容都应该是一个表达式,而不仅仅是变量名。是的,我们可以使用$ eq(mongDB中的Equal运算符)而不是$ gt < / p>

db.getCollection('Error_events_aggregated').aggregate([
{
    $project: {
        Site: 1,
        Event: 1,
        SubEvent: 1,
        Level: 1,
        NewLevel: {
            $switch: {
                branches: [
                    {
                        case: {$eq: ["$Event", "WorldEndingEvent"]}, /*Matches WorldEndingEvent*/
                        then: 4 
                    },
                    {
                        case: {$eq: ["$Event", "TheEvent"]}, /*Matches TheEvent*/
                        then: 2
                    },
                    {
                        case: {$eq: ["$Event", "AnEvent"]}, /*Matches AnEvent*/
                        then: 1
                    }
                ],
                default: "$Level"
                }
            }
        }
    }
])

如果此工作正常并且有任何其他更改,请告诉我。