尝试在mongodb 3.2

时间:2017-11-29 21:40:23

标签: mongodb aggregation-framework

我们假设我的收藏集中包含ExpName字段和Rname字段的文档。 Expname都是类型 - exp_1,exp_2等.Rname是一个例如4个破折号的字符串。 "作为-34rt-d3r5-4453f-ER4"

我需要根据实验名称进行汇总,并删除最后两个短划线之间的文本。在我上面给出的例子中,它将是" As-34rt-d3r5"

问题1)我如何将其纳入一个表格? 问题2)我以一种脏的方式为一个exp解决了这个问题,因为看起来字符的数量几乎是相同的,所以我可以采取前13个字符,这似乎是省略了最后两个破折号的子字符串。如果文字不那么统一,有没有正确的方法呢?

db.getCollection('rest01').aggregate(
{$match : {ExpName : "exp_1"}},
{$group: {_id :"$ExpName",_id : {$substr : ["$RName", 0,13]}, total: { $sum:1 }}
})

理想情况下,我希望得到一个名为Expname,Rnamesubstring,count的结果。此代码段仅供exp_1使用。是否有可能在一个结果中得到它?

1 个答案:

答案 0 :(得分:1)

以下是如何做到这一点:

db.getCollection('rest01').aggregate({
    $project: {
        "ExpName": 1,
        "splitRName": { $split: [ "$RName", "-" ] } // add an array with the constituents of your dash-delimited string id as a new field "splitRName"
    }
}, {
    $group: {
        _id: { // our group id shall be made up of both...
            "ExpName": "$ExpName", // ...the "ExpName" field...
            "Rnamesubstring": { // and some parts of the "RName" field
                $concat:
                [
                    { $arrayElemAt: [ "$splitRName", 0 ] },
                    "-",
                    { $arrayElemAt: [ "$splitRName", 1 ] },
                    "-",
                    { $arrayElemAt: [ "$splitRName", 2 ] }
                ]
            }
        },
        total: { $sum: 1 }
    }
})

如果您想在 MongoDB v3.2 (如评论中所述)中进行此操作,那么这里的内容并不完美但有效:

db.getCollection('rest01').aggregate({
    $group: {
        _id: { // our group id shall be made up of both...
            "ExpName": "$ExpName", // ...the "ExpName" field...
            "Rnamesubstring": {
                $substr:
                [
                    "$RName",
                    0,
                    {
                        $ifNull:
                        [
                            {
                                $arrayElemAt:
                                [{
                                    $filter: {
                                        input: {
                                            $map: {
                                                input: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 /* add numbers as required */ ],
                                                as: "index",
                                                in: {
                                                    $cond: {
                                                        if: { $eq: [ "-", { $substr: [ "$RName", "$$index", 1 ] } ] }, // if the string we look at is a dash...
                                                        then: "$$index", // ...then let's remember it
                                                        else: null // ...otherwise ignore it
                                                    }
                                                }
                                            }
                                        },
                                        as: "item",
                                        cond: { $ne: [ null, "$$item" ] } // get rid of all null values
                                    }
                                },
                                2 ] // we want the position of the third dash in the string (only)
                            },
                            1000 // in case of a malformed RName (wrong number of dashes or completely missing) we want the entire substring
                        ]
                    }
                ]
            }
        },
        total: { $sum: 1 }
    }
})

更新2:根据您的评论,您似乎遇到了一些与数据相关的问题(因此要么丢失RName值,要么缺少结构不合理的问题,即没有所需数量的带有破折号的部分)。我已经更新了v3.2的上述语句来处理这些行。但是,您可能希望了解哪些行实际导致此行为。可以使用以下语句轻松识别它们:

db.getCollection('rest01').aggregate({
    $project: {
        _id: 1,
        RName: 1,
        "Rnamesubstring": {
            $arrayElemAt:
            [{
                $filter: {
                    input: {
                        $map: {
                            input: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 /* add numbers as required */ ],
                            as: "index",
                            in: {
                                $cond: {
                                    if: { $eq: [ "-", { $substr: [ "$RName", "$$index", 1 ] } ] }, // if the string we look at is a dash...
                                    then: "$$index", // ...then let's remember it
                                    else: null // ...otherwise ignore it
                                }
                            }
                        }
                    },
                    as: "item",
                    cond: { $ne: [ null, "$$item" ] } // get rid of all null values
                }
            },
            2 ] // we want the position of the third dash in the string (only)
        }
    }
}, {
    $match: { "Rnamesubstring": { $exists:false } }
})