Luk*_*nka 6 mongodb mongodb-query aggregation-framework
我是 mongo 的新手,我需要你的帮助。
我有收藏studyProgramy。这是示例文档:
{
"_id" : "dGFY",
"garranti" : [
{
"typ" : {
"sk" : "garant",
"en" : "Chairman of study board"
},
"id" : "1025769"
},
{
"typ" : {
"sk" : "predseda odborovej komisie",
"en" : "Chairman of study board"
},
"id" : "1025769"
}
]
}
Run Code Online (Sandbox Code Playgroud)
接下来我收集osoby。
示例文档:
{
"_id" : "1025769",
"plneMeno" : "prof. RNDr. Peter Moczo, DrSc.",
"priezvisko" : "Moczo",
"meno" : "Peter",
"jeGarantProgramu" : "dGFY/x"
}
Run Code Online (Sandbox Code Playgroud)
我需要的是从增加documets osoby在阵列对应的文件garranti(其中studijneProgramy.garanti.id == osoby._id)。所以这是我想要的结果:
{
"_id" : "dGFY",
"garranti" : [
{
"typ" : {
"sk" : "garant",
"en" : "Chairman of study board"
},
"id" : "1025769"
"garant":{
"_id" : "1025769",
"plneMeno" : "prof. RNDr. Peter Moczo, DrSc.",
"priezvisko" : "Moczo",
"meno" : "Peter",
"jeGarantProgramu" : "dGFY/x"
}
},
{
"typ" : {
"sk" : "predseda odborovej komisie",
"en" : "Chairman of study board"
},
"id" : "1025769"
"garant":{
"_id" : "1025769",
"plneMeno" : "prof. RNDr. Peter Moczo, DrSc.",
"priezvisko" : "Moczo",
"meno" : "Peter",
"jeGarantProgramu" : "dGFY/x"
}
}
]
}
Run Code Online (Sandbox Code Playgroud)
我尝试了这种聚合,但它取代了garranti 的内容。
db.studijneProgramy.aggregate([
{
$lookup:
{
from:"osoby",
localField:"garranti.id",
foreignField:"_id",
as:"garranti.garant"
}
}
]
).pretty()
Run Code Online (Sandbox Code Playgroud)
任何帮助将不胜感激!
Nei*_*unn 18
MongoDB$lookup不会使用“查找”集合中的匹配项“更新”现有数组中的元素。它只会输出与给定条件匹配的“数组”,与您拥有的“现有数组”值或奇异值匹配。
为了将条目与“服务器”$lookup操作“合并”,您必须继续使用以下选项之一,以便以您想要的形式返回。
最简单的形式是简单地更改文档的结构,以便在您实际尝试“结合”相关信息之前,源中的每个数组成员首先是它自己的文档:
db.studijneProgramy.aggregate([
{ "$unwind": "$garranti" },
{ "$lookup": {
"from": "osoby",
"as": "garranti.garrant",
"localField": "garranti.id",
"foreignField": "_id"
}},
{ "$unwind": "$garranti.garrant" },
{ "$group": {
"_id": "$_id",
"garranti": { "$push": "$garranti" }
}}
])
Run Code Online (Sandbox Code Playgroud)
由于原始数组材料现在是单个文档,因此每个文档仅从连接的集合中接收匹配的“数组”。这将$unwind再次并最终使用$group以$push形成具有“连接”条目的最终数组形式。
在支持它是要使用的功能的版本的位爱好者$indexOfArray和$arrayElemAt以“匹配”的输出阵列$lookup,以在文档中的现有阵列条目:
db.studijneProgramy.aggregate([
{ "$lookup": {
"from": "osoby",
"as": "related",
"localField": "garranti.id",
"foreignField": "_id"
}},
{ "$project": {
"garranti": {
"$map": {
"input": "$garranti",
"in": {
"typ": "$$this.typ",
"id": "$$this.id",
"garrant": {
"$arrayElemAt": [
"$related",
{ "$indexOfArray": [ "$related._id", "$$this.id" ] }
]
}
}
}
}
}}
])
Run Code Online (Sandbox Code Playgroud)
因此,查找返回“匹配数组”(related),然后您“查找”这些匹配条目并通过 将它们转置为原始文档数组$map。当然,这需要一个额外的$project阶段或类似的步骤来重塑文档结果,因为您不能$lookup像前面提到的那样在输出中“定位”现有数组的每个元素。
这实际上是某些库(例如“mongoose”)为“在客户端上加入仿真”所做的“服务器”上的直接关联。实际上,“外部”条目被“映射”到现有数组上。
使用MongoDB 3.6 及更高版本提供的Uncorrelated 子查询的“子管道”处理的另一种选择,有点花哨和冗长。这里我们基本上是在“子管道”中进行操作,$lookup而不是在后续聚合阶段进行处理:
db.studijneProgramy.aggregate([
{ "$lookup": {
"from": "osoby",
"as": "garranti",
"let": { "garranti": "$garranti" },
"pipeline": [
{ "$match": {
"$expr": { "$in": [ "$_id", "$$garranti.id" ] }
}},
{ "$addFields": {
"docs": {
"$filter": {
"input": "$$garranti",
"cond": {
"$eq": [ "$$this.id", "$_id" ]
}
}
}
}},
{ "$unwind": "$docs" },
{ "$replaceRoot": {
"newRoot": {
"$mergeObjects": [
"$docs",
{ "garrant": {
"$arrayToObject": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"cond": { "$ne": [ "$$this.k", "docs"] }
}
}
}}
]
}
}}
]
}}
])
Run Code Online (Sandbox Code Playgroud)
这种将操作“放在头上”并有效地将“源文档”中的“匹配数组元素”作为数组放入每个匹配的外部元素中。
然后处理有效地使用$unwind过滤的源列表,然后合并来自外部集合的内容,因此现在看来$lookup“输出数组”实际上是来自“本地数组”的数据,现在与“外部内容”“合并”。
实际上,这只是对上述相同$map过程的更高级调用,但是在结果与覆盖原始数组属性的原始父文档合并之前对条目进行“关联” 。
我认为在某处有一个 JIRA,但我有一种感觉,“按设计工作”已标记在所有此类报告中,因此它不太可能从目前的情况改变。
所以你的误解是“加入”会“自动”与数组条目“合并”。它不是。
如果你想真正“合并数组输出”,那么上面的方法就是“服务器”方法。
| 归档时间: |
|
| 查看次数: |
4025 次 |
| 最近记录: |