我有mongo,以下结构的文件。我想获得父母中孩子的所有日期。
{"parent": 1, "child": "a", "date": "2016-02-01"},
{"parent": 1, "child": "a", "date": "2016-02-02"},
{"parent": 1, "child": "a", "date": "2016-02-03"},
{"parent": 1, "child": "b", "date": "2016-02-01"},
{"parent": 1, "child": "b", "date": "2016-02-03"},
{"parent": 2, "child": "a", "date": "2016-02-02"},
{"parent": 2, "child": "a", "date": "2016-02-03"},
{"parent": 2, "child": "b", "date": "2016-02-01"},
{"parent": 2, "child": "b", "date": "2016-02-02"}
为此,我使用聚合框架和以下管道来获取日期数组的数组。
{
$group: {
_id: {
parent: "$parent",
child: "$child"
},
dates: {
$push: "$date"
}
}
}, {
$group: {
_id: "$_id.parent",
dates: {
$push: "$dates"
}
}
}
输出结果如下:
[
{
"_id" : 1,
"dates" : [
[
"2016-02-01",
"2016-02-03"
],
[
"2016-02-01",
"2016-02-02",
"2016-02-03"
]
]
},
{
"_id" : 2,
"dates" : [
[
"2016-02-01",
"2016-02-02"
],
[
"2016-02-02",
"2016-02-03"
]
]
}
]
我现在想要获取每个文档的2d数组中的所有常见日期,并尝试使用$projection
添加$setIntersection
阶段。但据我所知,$setIntersection
需要一组定义明确的字段或数组 - 使用$setIntersection: "$dates"
不能按预期工作。
感谢任何帮助!
附加信息:子类型的数量是可变的
预期产出:
[
{
"_id" : 1.0000000000000000,
"dates" : [
"2016-02-01",
"2016-02-03"
]
},
{
"_id" : 2.0000000000000000,
"dates" : [
"2016-02-02"
]
}
]
答案 0 :(得分:1)
使用MongoDB 3.2,您可以使用$arrayElemAt
获取两个维度的每个元素并将其提供给$setIntersection
:
db.collection.aggregate([
{ "$group": {
"_id": {
"parent": "$parent",
"child": "$child"
},
"dates": { "$push": "$date" }
}},
{ "$group": {
"_id": "$_id.parent",
"dates": { "$push": "$dates" }
}},
{ "$project": {
"dates": {
"$setIntersection": [
{ "$arrayElemAt": [ "$dates", 0 ] },
{ "$arrayElemAt": [ "$dates", 1 ] }
]
}
}}
])
但实际上,您正在考虑的特定问题可以通过更加简化的方式解决。基本上你需要做的就是计算父母每个日期的孩子出生率。任何超过一个表示有两个或更多孩子分享日期:
db.collection.aggregate([
{ "$group": {
"_id": {
"parent": "$parent",
"date": "$date"
},
"count": { "$sum": 1 }
}},
{ "$match": { "count": { "$gt": 1 } } },
{ "$group": {
"_id": "$_id.parent",
"dates": { "$push": "$_id.date" }
}}
])
所以没有理由比较数组,因为分组元素的简单计数告诉你"设置交集"会的。
同样的原则适用于引入聚合框架的每个MongoDB版本。
两者都给你相同的结果:
{ "_id" : 1, "dates" : [ "2016-02-03", "2016-02-01" ] }
{ "_id" : 2, "dates" : [ "2016-02-02" ] }
同时注意到"设置"不被认为是有序的,也不是从$group
发出的键的顺序。
答案 1 :(得分:1)
这里可以做的是计算父母子女的数量,并计算父母每个孩子的日期数。
然后获取所有日期,其中日期的数量等于父项的子项数,这将给出预期的输出。
这是我尝试过的,但可能有更好的解决方案。
db.coll.aggregate([
{
$group: {
_id: {
parent: "$parent",
child: "$child"
},
dates: {
$push: "$date"
}
}
},
{
$group: {
_id: "$_id.parent",
total_children: {$sum : 1},
dates: {
$push: "$dates"
}
}
},
{
$unwind : "$dates"
},
{
$unwind : "$dates"
},
{
$group : {
_id : {
parent : "$_id",
dates : "$dates"
},
total_children : {$first : "$total_children"},
total_dates : {$sum : 1}
}
},
{
$project : {
_id : 1,
tempEq : {$eq : ["$total_children", "$total_dates"]}
}
},
{
$match : {'tempEq' : true}
},
{
$group : {
_id : '$_id.parent',
dates : {$addToSet : "$_id.dates"}
}
}
])
这给出了以下输出:
{ "_id" : 1, "dates" : [ "2016-02-01", "2016-02-03" ] }
{ "_id" : 2, "dates" : [ "2016-02-02" ] }
希望这有帮助。