在不覆盖现有值的情况下使用 $lookup “填充”字段

Joh*_*Rin 2 mongodb mongodb-query aggregation-framework

考虑以下文件:

一份communications文件

{
    "_id" : ObjectId("5c069a6acbd69e0f61983850"),
    "type" : "request",
    "title" : "test 1",
    "messages" : [ 
        {
            "authorId" : "7b0dcd22-c3bb-426f-8235-671b82acee98",
            "body" : "test 1",
            "createdAt" : ISODate("2018-12-04T15:16:58.342Z")
        }
    ],
    "receivers" : [ 
        "e75f3849-09bb-46a4-a05d-885b6d31ccc3"
    ]
}
Run Code Online (Sandbox Code Playgroud)

一份users文件

{
    "_id" : "7b0dcd22-c3bb-426f-8235-671b82acee98",
    "userInfo" : {
        "avatarKey" : "7b0dcd22-c3bb-426f-8235-671b82acee98/avatars/Dandelion.png",
        "familyName" : "Doe",
        "givenName" : "John"
    }
}
Run Code Online (Sandbox Code Playgroud)

蒙戈外壳,我尝试检索communicationsmessages.authorId“居住”与userInfo我的领域user文档。

我试图用这样的方法来做到这$lookup一点:

db.communications.aggregate([
   {
     $lookup:
       {
         from: "users",
         localField: "messages.authorId",
         foreignField: "_id",
         as: "messages.authorId"
       }
  }
])
Run Code Online (Sandbox Code Playgroud)

但该字段messages.authorId被覆盖。

如何在userInfo不替换现有值的情况下“填充”我的字段?

谢谢你的帮助。

Ash*_*shh 6

Because your messages is an array field it overwrites the existing array with the new object as you provide the .dot notation in the as ("messages.authorId") expression.

So if you want to populate each user inside messages the array You need to $unwind the messages array first to add a new key and then $group to roll back again into array.

db.communications.aggregate([
  { "$unwind": "$messages" },
  { "$lookup": {
    "from": "users",
    "localField": "messages.authorId",
    "foreignField": "_id",
    "as": "messages.authorId"
  }},
  { "$unwind": "$messages.authorId" },
  { "$group": {
    "_id": "$_id",
    "messages": { "$push": "$messages" },
    "type": { "$first": "$type" },
    "title": { "$first": "$title" },
    "receivers": { "$first": "$receivers" }
  }}
])
Run Code Online (Sandbox Code Playgroud)