应用具有可更改数组大小的$ group聚合

时间:2018-04-04 11:01:15

标签: mongodb aggregation-framework

我有以下文件:

//doc 1
{
    "_id" : ObjectId("5ac392f15c592414ec99d630"), 
    "nv" : "de", 
    "nid" : 1.0, 
    "coc" : 3.0, 
    "seg" : {
        "segid" : 0.0, 
        "attv" : [
            {
                "id" : 1.0, 
                "v" : 5.0
            }, 
            {
                "id" : 2.0, 
                "v" : 4.0
            }
        ], 
        "devattv" : [
            {
                "id" : 1.0, 
                "v" : 2.0, 
                "t" : 1.0
            }, 
            {
                "id" : 1.0, 
                "v" : 3.0, 
                "t" : 2.0
            }, 
            {
                "id" : 2.0, 
                "v" : 2.0, 
                "t" : 1.0
            }, 
            {
                "id" : 2.0, 
                "v" : 2.0, 
                "t" : 2.0
            }
        ]
    }
}
//doc 2
{ 
    "_id" : ObjectId("5ac396565c592414ec99d64f"), 
    "nv" : "de", 
    "nid" : 1.0, 
    "coc" : 4.0, 
    "seg" : {
        "segid" : 0.0, 
        "attv" : [
            {
                "id" : 1.0, 
                "v" : 5.0
            }, 
            {
                "id" : 2.0, 
                "v" : 4.0
            }
        ], 
        "devattv" : [
            {
                "id" : 1.0, 
                "v" : 2.0, 
                "t" : 1.0
            }, 
            {
                "id" : 1.0, 
                "v" : 3.0, 
                "t" : 2.0
            }, 
            {
                "id" : 2.0, 
                "v" : 2.0, 
                "t" : 1.0
            }, 
            {
                "id" : 2.0, 
                "v" : 2.0, 
                "t" : 2.0
            }
        ]
    }
}
//doc 3
{ 
    "_id" : ObjectId("5ac498f15c592414ec99d6c8"), 
    "nv" : "de", 
    "nid" : 1.0, 
    "coc" : 6.0, 
    "seg" : {
        "segid" : 0.0, 
        "attv" : [
            {
                "id" : 1.0, 
                "v" : 5.0
            }, 
            {
                "id" : 2.0, 
                "v" : 4.0
            }
        ], 
        "devattv" : [
            {
                "id" : 1.0, 
                "v" : 2.0, 
                "t" : 1.0
            }, 
            {
                "id" : 1.0, 
                "v" : 1.0, 
                "t" : 2.0
            }, 
            {
                "id" : 1.0, 
                "v" : 2.0, 
                "t" : 3.0
            }, 
            {
                "id" : 2.0, 
                "v" : 1.0, 
                "t" : 1.0
            }, 
            {
                "id" : 2.0, 
                "v" : 1.0, 
                "t" : 2.0
            }, 
            {
                "id" : 2.0, 
                "v" : 2.0, 
                "t" : 3.0
            }
        ]
    }
}

我需要的最终结果是:

{
    "_id": 1,
    "nv": "de",
    "coc": 13,
    "attv": [{
        "_id": 1,
        "vsum": 15
    }, {
        "_id": 2,
        "vsum": 12
    }],
    "devattv": [{
        "_id": 1,
        "dvsum": 6,
        "t": 1
    }, {
        "_id": 1,
        "dvsum": 7,
        "t": 2
    }, {
        "_id": 2,
        "dvsum": 5,
        "t": 1
    }, {
        "_id": 2,
        "dvsum": 5,
        "t": 2
    }, {
        "_id": 1,
        "dvsum": 2,
        "t": 3
    }, {
        "_id": 2,
        "dvsum": 2,
        "t": 3
    }]
}

我尝试过的聚合管道是:

db.collection.aggregate([
{
    "$unwind": {
        "path": "$seg.attv",
        "preserveNullAndEmptyArrays": true
    }
}, {
    "$unwind": {
        "path": "$seg.devattv",
        "preserveNullAndEmptyArrays": true
    }
},
{
  "$redact": {
    "$cond": [
    { "$eq": [ "$seg.attv.id", "$seg.devattv.id" ] },
    "$$KEEP",
    "$$PRUNE"
    ]
    }
},
{
    "$group": {
        "_id": {
            "nid": "$nid",
            "attvid": "$seg.attv.id",
            "devattvid": "$seg.devattv.id",
            "t": "$seg.devattv.t"
        },
        "vsum": { "$sum": "$seg.attv.v"},
        "dvsum": { "$sum": "$seg.devattv.v"},
        "nv": { "$first": "$nv" },
        "coc": { "$sum": "$coc" }
    }
},
{
    "$group": {
        "_id": "$_id.nid",
        "nv": { "$first": "$nv" },
        "coc": { "$first": "$coc" },
        "attv": {
            "$addToSet": {
                "_id": {
                    "$ifNull": ["$_id.attvid", 0]
                },
                "vsum": "$vsum",
            }
        },
        "devattv": {
            "$addToSet": {
                "_id": {
                    "$ifNull": ["$_id.devattvid", 0]
                },
                "dvsum": "$dvsum",
                "t": "$_id.t"
            }
        }
    }
}
])

但我得到的最终结果是错误的:

{
    "_id": 1,
    "nv": "de",
    "coc": 6,
    "attv": [{
        "_id": 1,
        "vsum": 15
    }, {
        "_id": 2,
        "vsum": 12
    }, {
        "_id": 1,
        "vsum": 5
    }, {
        "_id": 2,
        "vsum": 4
    }],
    "devattv": [{
        "_id": 1,
        "dvsum": 6,
        "t": 1
    }, {
        "_id": 1,
        "dvsum": 7,
        "t": 2
    }, {
        "_id": 2,
        "dvsum": 5,
        "t": 1
    }, {
        "_id": 2,
        "dvsum": 5,
        "t": 2
    }, {
        "_id": 1,
        "dvsum": 2,
        "t": 3
    }, {
        "_id": 2,
        "dvsum": 2,
        "t": 3
    }]
}

doc 1 doc 2 attvdevattv数组大小为2但 doc 3 有数组attv的大小为2,devattv的数组大小为3。 我理解为什么聚合管道会产生这个结果,但我不知道如何解决这个问题。有人有什么建议吗?

修改

如果在聚合代码片段中不清楚我想要实现的目标。我试图将展平数组v中的attv以及其他展平数组v中的devattv求和。如下所示:

"vsum": { "$sum": "$seg.attv.v"},
"dvsum": { "$sum": "$seg.devattv.v"}

并按以下字段分组:

"nid": "$nid",
"attvid": "$seg.attv.id",
"devattvid": "$seg.devattv.id",
"t": "$seg.devattv.t"

问题是由第3个文件引起的。如果我只使用doc 1doc 2执行此操作,那么一切都很好。但是,一旦我添加doc 3数组大小与其他数据不匹配,结果就错了。

0 个答案:

没有答案