我是mongo新手,需要您的帮助。
我收藏了 studijneProgramy 。这是示例文档:
{
"_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"
}
]
}
下一步,我收集了 osoby 。
示例文件:
{
"_id" : "1025769",
"plneMeno" : "prof. RNDr. Peter Moczo, DrSc.",
"priezvisko" : "Moczo",
"meno" : "Peter",
"jeGarantProgramu" : "dGFY/x"
}
我需要的是将 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"
}
}
]
}
我尝试了这种汇总,但是它替换了 garranti 的内容。
db.studijneProgramy.aggregate([
{
$lookup:
{
from:"osoby",
localField:"garranti.id",
foreignField:"_id",
as:"garranti.garant"
}
}
]
).pretty()
任何帮助将不胜感激!
答案 0 :(得分:2)
MongoDB $lookup
不会使用“ lookup”集合中的匹配项来“更新”现有数组中的元素。它将仅输出与给定条件匹配的“数组”,即与您所拥有的值的“现有数组”或奇异值匹配的结果。
要通过“服务器” $lookup
操作“合并”条目,您必须继续使用以下选项之一,以便以所需的形式返回。
最简单的形式是简单地更改文档的结构,以使源中的每个数组成员首先是它的自己的文档,然后再实际尝试“关联”相关信息:< / p>
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" }
}}
])
由于原始数组材料现在是单个文档,因此每个仅从合并的集合中接收匹配项的“数组”。这将再次$unwind
,最后使用$group
,以便$push
成为具有“ joined”条目的最终数组形式。
在支持它的版本中,有些幻想是使用$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" ] }
]
}
}
}
}
}}
])
因此,查找返回“匹配数组”(related
),然后您“查找”这些匹配项,并通过$map
将它们转置为原始文档数组。当然,这需要额外的$project
阶段或类似步骤才能重塑文档结果,因为您不能像前面提到的那样“定位” $lookup
输出中现有数组的每个元素。
这实际上是某些服务器(例如“猫鼬”)为“在客户端上进行联合仿真”所做的工作在“服务器”上的直接关联。实际上,“外来”条目被“映射”到现有阵列上。
使用“子管道”处理对MongoDB 3.6及更高版本的Uncorrelated subquery进行处理的另一种选择是有点幻想和漫不经心。在这里,我们基本上在$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"] }
}
}
}}
]
}
}}
]
}}
])
这种操作使操作“顺其自然”,并将“源文档”中的“匹配数组元素”有效地放置到每个匹配的外部元素数组中。
然后,该处理有效地在过滤的源列表上使用$unwind
,然后合并来自外部集合的内容,因此现在看来$lookup
“输出数组”实际上是来自“本地”的数据数组”现在与“外国内容”“合并”。
确实,这只是上面相同的$map
流程的更高级的调用,但是在之前对条目进行“关联”,结果与原始父文档合并,从而覆盖了原始array属性
我认为某个地方可以使用JIRA,但是我感觉在所有此类报告中都标有“按设计工作” ,因此不太可能对其进行更改目前确实如此。
因此,您对“ join”的误解将“自动”与数组项“合并”。不会。
如果您想实际“合并数组输出”,那么上述方法就是“服务器”方法。
答案 1 :(得分:0)
除了dege指出的潜在重复项之外,如果数据量不大,则可以按以下方式使用JS。我相信使用聚合和$ lookup会更快,但这更干净。
db.studijneProgramy.find().forEach(stu=>{
stu.garranti=stu.garranti.map(gar=>{
gar.garant=db.osoby.find({_id:gar.id})[0];
return gar;
});
db.studijneProgramy.save(stu);
});