Mongo 在二维数组的单个字段上设置交集
Mongo set intersection on single field which is a 2d array
我在 mongo 中有以下结构的文件。我想在 parent 中获取 children 的所有常见日期。
{"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"
]
]
}
]
我现在想要获取每个文档的二维数组中的所有公共日期,并且我尝试添加 $projection
阶段和 $setIntersection
。但据我了解,$setIntersection
需要一组定义明确的字段或数组 - 使用 $setIntersection: "$dates"
无法按预期工作。
感谢任何帮助!
附加信息:child 类型的数量是可变的
预期输出:
[
{
"_id" : 1.0000000000000000,
"dates" : [
"2016-02-01",
"2016-02-03"
]
},
{
"_id" : 2.0000000000000000,
"dates" : [
"2016-02-02"
]
}
]
那么在 MongoDB 3.2 中你可以使用 $arrayElemAt
to get each element of the two dimensions and feed that to $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 ] }
]
}
}}
])
但实际上,您正在查看的特定问题可以通过更简单的方式解决。基本上您需要做的就是计算 parent 每个日期出现的 child 次。超过一个表示有两个或更多 children 共享日期:
db.collection.aggregate([
{ "$group": {
"_id": {
"parent": "$parent",
"date": "$date"
},
"count": { "$sum": 1 }
}},
{ "$match": { "count": { "$gt": 1 } } },
{ "$group": {
"_id": "$_id.parent",
"dates": { "$push": "$_id.date" }
}}
])
因此没有理由比较数组,因为简单的分组元素计数就可以告诉您 "set intersection" 是什么。
同样的原则适用于引入聚合框架的每个 MongoDB 版本。
两者都给你相同的结果:
{ "_id" : 1, "dates" : [ "2016-02-03", "2016-02-01" ] }
{ "_id" : 2, "dates" : [ "2016-02-02" ] }
还注意到 "sets" 不被认为是有序的,$group
发出的键的顺序也不被认为是有序的。
这里可以做的是统计一个parent的child人的个数,统计一个parent的每个child的日期数。
然后获取日期数等于 parent 的 children 数的所有日期,这将给出预期的输出。
这是我尝试过的方法,但可能会有更好的解决方案。
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" ] }
希望对您有所帮助。
我在 mongo 中有以下结构的文件。我想在 parent 中获取 children 的所有常见日期。
{"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"
]
]
}
]
我现在想要获取每个文档的二维数组中的所有公共日期,并且我尝试添加 $projection
阶段和 $setIntersection
。但据我了解,$setIntersection
需要一组定义明确的字段或数组 - 使用 $setIntersection: "$dates"
无法按预期工作。
感谢任何帮助!
附加信息:child 类型的数量是可变的
预期输出:
[
{
"_id" : 1.0000000000000000,
"dates" : [
"2016-02-01",
"2016-02-03"
]
},
{
"_id" : 2.0000000000000000,
"dates" : [
"2016-02-02"
]
}
]
那么在 MongoDB 3.2 中你可以使用 $arrayElemAt
to get each element of the two dimensions and feed that to $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 ] }
]
}
}}
])
但实际上,您正在查看的特定问题可以通过更简单的方式解决。基本上您需要做的就是计算 parent 每个日期出现的 child 次。超过一个表示有两个或更多 children 共享日期:
db.collection.aggregate([
{ "$group": {
"_id": {
"parent": "$parent",
"date": "$date"
},
"count": { "$sum": 1 }
}},
{ "$match": { "count": { "$gt": 1 } } },
{ "$group": {
"_id": "$_id.parent",
"dates": { "$push": "$_id.date" }
}}
])
因此没有理由比较数组,因为简单的分组元素计数就可以告诉您 "set intersection" 是什么。
同样的原则适用于引入聚合框架的每个 MongoDB 版本。
两者都给你相同的结果:
{ "_id" : 1, "dates" : [ "2016-02-03", "2016-02-01" ] }
{ "_id" : 2, "dates" : [ "2016-02-02" ] }
还注意到 "sets" 不被认为是有序的,$group
发出的键的顺序也不被认为是有序的。
这里可以做的是统计一个parent的child人的个数,统计一个parent的每个child的日期数。
然后获取日期数等于 parent 的 children 数的所有日期,这将给出预期的输出。
这是我尝试过的方法,但可能会有更好的解决方案。
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" ] }
希望对您有所帮助。