我有以下文件:
//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 在attv
和devattv
数组大小为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 1
和doc 2
执行此操作,那么一切都很好。但是,一旦我添加doc 3
数组大小与其他数据不匹配,结果就错了。