MongoDB aggregate selective project

后端 未结 1 1489
离开以前
离开以前 2021-02-06 06:05

I am running into problems reshaping my document during aggregation for grouping. Basically I want to push entries to fields depending in their type. I have a structure as follo

1条回答
  •  星月不相逢
    2021-02-06 06:40

    You seemed on the right track, there are just different approaches to removing those values of false from the conditional. You cannot have it return nothing, but you cn get rid of the values you do not want.

    If you truly want "sets" and you have MongoDB 2.6 or greater available, then you basically filter out the false values using $setDifference:

    db.entities.aggregate([
        { "$unwind": "$entities" },
        { "$group": {
            "_id": "$_id",
            "A": { 
                "$addToSet": {
                    "$cond": [
                        { "$eq": [ "$entities.type", "A" ] },
                        "$entities.val",
                        false
                    ]
                }
            },
            "B": { 
                "$addToSet": {
                    "$cond": [
                        { "$eq": [ "$entities.type", "B" ] },
                        "$entities.val",
                        false
                    ]
                }
            }
        }},
        { "$project": {
            "A": {
                "$setDifference": [ "$A", [false] ]
            },
            "B": {
                "$setDifference": [ "$B", [false] ]
            }
        }}
    ])
    

    Or just as one step using the $map operator inside $project:

    db.entities.aggregate([
        {"$project": {
            "A": {
                 "$setDifference": [
                     {
                         "$map": {
                             "input": "$entities",
                             "as": "el",
                             "in": {
                                 "$cond": [
                                     { "$eq": [ "$$el.type", "A" ] },
                                     "$$el.val",
                                     false
                                 ]
                             }
                         }
                     },
                     [false]
                 ]
             },
            "B": {
                 "$setDifference": [
                     {
                         "$map": {
                             "input": "$entities",
                             "as": "el",
                             "in": {
                                 "$cond": [
                                     { "$eq": [ "$$el.type", "B" ] },
                                     "$$el.val",
                                     false
                                 ]
                             }
                         }
                     },
                     [false]
                 ]
             }
        }}
    ])
    

    Or otherwise stay with general $unwind and $match operators to filter these:

    db.entities.aggregate([
        { "$unwind": "$entities" },
        { "$group": {
            "_id": "$_id",
            "A": { 
                "$push": {
                    "$cond": [
                        { "$eq": [ "$entities.type", "A" ] },
                        "$entities.val",
                        false
                    ]
                }
            },
            "B": { 
                "$push": {
                    "$cond": [
                        { "$eq": [ "$entities.type", "B" ] },
                        "$entities.val",
                        false
                    ]
                }
            }
        }},
        { "$unwind": "$A" },
        { "$match": { "A": { "$ne": false } } },
        { "$group": {
            "_id": "$_id",
            "A": { "$push": "$A" },
            "B": { "$first": "$B" }
        }},
        { "$unwind": "$B" },
        { "$match": { "B": { "$ne": false } } },
        { "$group": {
            "_id": "$_id",
            "A": { "$first": "$A" },
            "B": { "$push": "$B" }
        }}
    ])
    

    Using either $push for normal arrays or $addToSet for unique sets.

    0 讨论(0)
提交回复
热议问题