mongodb $ lookup用于投影数组中的嵌套对象

问题描述

在聚合管道中使用$ lookup时遇到问题。

我有2个收藏集,membersmessages

成员:

{_id,FirstName,LastName,Email,...}

消息

{
  _id:ObjectId('xxx'),createdBy:ObjectId(''),...
  threads:[
    {  message:'',attachments:[],from:ObjectId,to:[{status:'Read',recipient:ObjectId}] }]
}

我想做的是

to:[{status:'Read',recipient:ObjectId}]中查找每个收件人,并填充成员集合中的姓名和电子邮件

我尝试了很多类似的事情。 //

db.messages.aggregate([
     {
                '$lookup': {
                    'from': 'members','let': {
                        'memberId': '$threads.to.recipient'
                    },'pipeline': [
                        {
                            '$match': {
                                '$expr': {
                                    '$eq': [
                                        '$$memberId','$members._id'
                                    ]
                                }
                            }
                        },{$project: {FirstName: 1,_id: 1,LastName: 1,Email: 1}}
                    ],'as': 'members'
                }
            }
    ]

包括查询在内的许多不同查询总是返回成员的[]('as':'members')。

只是测试一下,我对猫鼬和.populate('threads.to.recipient','FirstName')的工作非常满意。但是我不能使用猫鼬,而必须使用MongoDB的本地nodejs驱动程序。

对此,任何建议将不胜感激。

解决方法

在执行$ lookup之前,必须使用$unwind来展平threads数组的结构

db.messages.aggregate([
  {
    $unwind: "$threads"
  },{
    $unwind: "$threads.to"
  },{
    $lookup: {
      from: "members",let: {
        memberId: "$threads.to.recipient"
      },as: "members",pipeline: [
        {
          $match: {
            $expr: {
              $eq: [
                "$$memberId","$_id"
              ]
            }
          }
        },{
          $project: {
            FirstName: 1,_id: 1,LastName: 1,Email: 1
          }
        }
      ]
    }
  }
])

See the working example in MongoDB Playground

如果您不想使用$ unwind,只需尝试以下查询:

db.messages.aggregate([
  {
    "$lookup": {
      "from": "members","localField": "threads.to.recipient","foreignField": "_id","as": "members"
    }
  }
])

See the working example in MongoDB Playground