我有两个样本集
我想:
我在问题按钮上尝试了3种方法。每个人都需要我的一个要求。希望有人能填补它。
请注意。你可以说为什么不在相同的集合regionInfo中的govenor信息。我有理由说“govenor”集合也与其他集合相关联。 所以,我需要单独的“govenor”系列。
govenor
[{
"_id" : "007",
"name" : {
"fname" : "Joe",
"lname" : "McDee",
}
},
{
"_id" : "008",
"name" : {
"fname" : "Martin",
"lname" : "Neilwel",
}
}]
regionInfo
{
"country_id" : 328,
"country_name" : "UK",
}
"regions" : [{
"region_id" : 001,
"region_name" : "west midlands",
"govenor_id" : "007"
},
{
"region_id" : 002,
"region_name" : "east midlands"
"govenor_id" : "008"
}
],
"cities" : [{
"city_id" : 1,
"region_id" : 001,
"city_name" : "Birmingham"
}, {
"city_id" : 2,
"region_id" : 001,
"city_name" : "coventry"
}, {
"city_id" : 3,
"region_id" : 001,
"city_name" : "warsaw"
}, {
"city_id" : 4,
"region_id" : 002,
"city_name" : "dudley"
},
{
"city_id" : 5,
"region_id" : 002,
"city_name" : "blabla"
}]
}
期望的结果:
{
"_id" : { "country_name" : "UK", "number_of_region" : 2 },
"regions" : [
{
"region_name" : "west midlands",
"govenor.fname" : "Joe",
"cities_in_region" : 3
},
{
"region_name" : "east midlands",
"govenor.fname" : "Martin",
"cities_in_region" : 2
}
]
}
我找不到这个城市的数量:
db.collection('regionInfo').aggregate( [
{ '$unwind': "regionInfo" },
{ '$lookup':{
from: "govenor",
localField: 'regionInfo.govenor_id',
foreignField: "_id",
as: "Gjoin"
}},
{ '$lookup': {
from: "regionInfo",
localField: 'regions.region_id',
foreignField: "cities.gevenor_id",
as: "govjoin"
}},
{ '$project' : {
R_id: "$regionInfo.region_name",
govenor_fname:"$Gjoin..name.fname",
govenor_lname:"$Gjoin.name.lname",
}}
])
如果我使用mapReduce,我可以计算城市(格式不正确)而不加入govenor信息
map = function(){
for (var index = 0; index < this.regions.length; ++index) {
var auth = this.regions[ index ];
emit( auth._id ,{cmt : {'this.cities.region_id' :'this.regions.region_id'}} );
}}
reduce = function(auth, counters) {
count = 0;
for (var index = 0; index < counters.length; ++index) {
count += counters[index];
}
return count;
}
这是Neil Lunn的My Fav Method。但我需要实施加入govenor信息:
db.collection.find().map(doc => ({
_id: {
country_name: doc.country_name,
number_of_regions: doc.regions.length
},
regions: doc.regions.map( r => ({
region_name: r.region_name,
cities_in_region: doc.cities.filter( c =>
c.region_id === r.region_id ).length })
)
}))
答案 0 :(得分:1)
为了做到这一点,你基本上想要遵循我首先给你$project
阶段的基本“重塑”声明的模式。然后在$unwind
之前执行"regions"
数组上的$lookup
,因为您需要这样做,因为$lookup
无法将输出“放在”数组中:
db.getCollection('regionInfo').aggregate([
{ "$project": {
"_id": {
"country_name": "$country_name",
"number_of_region": { "$size": "$regions" }
},
"regions": {
"$map": {
"input": "$regions",
"as": "r",
"in": {
"region_name": "$$r.region_name",
"govenor_fname": "$$r.govenor_id",
"cities_in_region": {
"$size": {
"$filter": {
"input": "$cities",
"as": "c",
"cond": { "$eq": [ "$$c.region_id", "$$r.region_id" ] }
}
}
}
}
}
}
}},
{ "$unwind": "$regions" },
{ "$lookup": {
"from": "govenor",
"localField": "regions.govenor_fname",
"foreignField": "_id",
"as": "regions.govenor_fname"
}},
{ "$addFields": {
"regions.govenor_fname": {
"$arrayElemAt": [
"$regions.govenor_fname.name.fname",
0
]
}
}},
{ "$group": {
"_id": "$_id",
"regions": { "$push": "$regions" }
}}
])
对于第一部分,它全部发生在$project
内,因为我们只是改变文档的形状,就像在JavaScript示例中演示的那样简单地重塑事物。
您想要的“计数”实际上是通过从文档中的各个数组中获取$size
来实现的。第一个是包含"regions"
数组的简单“大小”。
每个“区域”内的“城市”的第二个“计数”是通过在"cities"
数组上使用$filter
来完成的,以匹配当前的“区域”。然后,简单地测试过滤后的列表的“大小”。
由于"regions"
是一个“数组”,我们想要加入另一个集合,我们需要先对它进行“去规范化”。 $unwind
通过为每个数组成员创建文档副本来执行此操作。
然后$lookup
可以引用我们实际重命名的提供的"govenor_id"
到早期阶段的目标字段。我们在那里重命名,因此结果文档中的顺序不会改变。
由于$lookup
的结果也是一个数组(因为它可能匹配很多),我们知道它在这里是一个1:1
关系,所以我们只需从第一个数组索引中获取$arrayElemAt
的结果。
在$addFields
管道阶段发生这种情况,我们只能“指定'新'字段而不是所有字段。这是在MongoDB 3.4中添加的,但是在早期版本中(3.2因为我们使用$lookup
),我们需要使用$project
明确指定所有字段。
现在剩下的就是在$unwind
之前的状态下将文档重新组合在一起,因此我们使用$group
管道阶段以便按文档“分组”{ {1}}和$push
将所有_id
数据恢复为数组形式。
然后输出:
"regions"
还修复了您的数据,因为它在多个地方都有格式错误。 {
"_id" : {
"country_name" : "UK",
"number_of_region" : 2
},
"regions" : [
{
"region_name" : "west midlands",
"govenor_fname" : "Joe",
"cities_in_region" : 3
},
{
"region_name" : "east midlands",
"govenor_fname" : "Martin",
"cities_in_region" : 2
}
]
}
集合保持不变:
<强> regionInfo 强>
"govenor"