MongoDB:使用带有$ regex的$ cond进行聚合

时间:2018-04-04 19:05:33

标签: regex mongodb conditional aggregation-framework grouping

我正在尝试将数据分组到多个阶段。

目前我的查询如下:

db.captions.aggregate([
{$project: {
    "videoId": "$videoId",
    "plainText": "$plainText",
    "Group1": {$cond: {if: {$eq: ["plainText", {"$regex": /leave\sa\scomment/i}]}, 
        then: "Yes", else: "No"}}}}
])

我不确定在聚合阶段是否可以在$ cond中使用$ regex运算符。非常感谢你的帮助!

提前致谢

1 个答案:

答案 0 :(得分:3)

正如我在上面的评论中所写,$regex目前在$cond内部无效。有一个开放的JIRA ticket,但它是,呃,好吧,开放......

在您的具体情况下,我倾向于建议您在客户端解决该主题,除非您处理的是疯狂数量的输入数据,您将始终只返回小的子集。根据您的查询判断,您似乎总是要将所有文档检索到两个结果组(“是”和“否”)。

如果您不希望或无法在客户端解决该主题,那么这里使用的是$facet(需要MongoDB> = v3.4) - 它既不是特别快也不是过于漂亮但是它可能会帮助你开始。

db.captions.aggregate([{
    $facet: { // create two stages that will be processed using the full input data set from the "captions" collection
        "CallToActionYes": [{ // the first stage will...
            $match: { // only contain documents...
                "plainText": /leave\sa\scomment/i // that are allowed by the $regex filter (which could be extended with multiple $or expressions or changed to $in/$nin which accept regular expressions, too)
            }
        }, {
            $addFields: { // for all matching documents...
                "CallToAction": "Yes" // we create a new field called "CallsToAction" which will be set to "Yes"
            }
        }],
        "CallToActionNo": [{ // similar as above except we're doing the inverse filter using $not
            $match: {
                "plainText": { $not: /leave\sa\scomment/i }
            }
        }, {
            $addFields: {
                "CallToAction": "No" // and, of course, we set the field to "No"
            }
        }]
    }
}, {
    $project: { // we got two arrays of result documents out of the previous stage
        "allDocuments" : { $setUnion: [ "$CallToActionYes", "$CallToActionNo" ] } // so let's merge them into a single one called "allDocuments"
    }
}, {
    $unwind: "$allDocuments" // flatten the "allDocuments" result array
}, {
    $replaceRoot: { // restore the original document structure by moving everything inside "allDocuments" up to the top
        newRoot: "$allDocuments"
    }
}, {
    $project: { // include only the two relevant fields in the output (and the _id)
        "videoId": 1,
        "CallToAction": 1
    }
}])

与聚合框架一样,它可能有助于从管道末端删除各个阶段并运行部分查询,以便了解每个阶段的作用。