使用管道中数组中的对象值执行 $lookup

Perform $lookup with object value in array from pipeline

所以我有 3 个模型 userpropertytestimonials

客户评价有 propertyIdmessageuserId。我已经能够通过管道获得每个 属性 的所有推荐。

Property.aggregate([
  { $match: { _id: ObjectId(propertyId) } },
  {
      $lookup: {
        from: 'propertytestimonials',
        let: { propPropertyId: '$_id' },
        pipeline: [
          {
            $match: {
              $expr: {
                $and: [{ $eq: ['$propertyId', '$$propPropertyId'] }],
              },
            },
          },
        ],
        as: 'testimonials',
      },
    },
]) 

返回的 属性 看起来像这样

{
 .... other property info,
 testimonials: [
  {
    _id: '6124bbd2f8eacfa2ca662f35',
    userId: '6124bbd2f8eacfa2ca662f29',
    message: 'Amazing property',
    propertyId: '6124bbd2f8eacfa2ca662f2f',
  },
  {
    _id: '6124bbd2f8eacfa2ca662f35',
    userId: '6124bbd2f8eacfa2ca662f34',
    message: 'Worth the price',
    propertyId: '6124bbd2f8eacfa2ca662f2f',
  },
 ]
}

用户架构

firstName: {
  type: String,
  required: true,
},
lastName: {
  type: String,
  required: true,
},
email: {
  type: String,
  required: true,
},

属性 架构

name: {
  type: String,
  required: true,
},
price: {
  type: Number,
  required: true,
},
location: {
  type: String,
  required: true,
},

推荐架构

propertyId: {
  type: ObjectId,
  required: true,
},
userId: {
  type: ObjectId,
  required: true,
},
testimonial: {
  type: String,
  required: true,
},

现在的问题是我如何 $lookup 来自每个推荐的 userId 以便显示用户的信息而不仅仅是每个推荐中的 id?

我希望我的回复结构如下

{
    _id: '6124bbd2f8eacfa2ca662f34',
    name: 'Maisonette',
    price: 100000,
    testimonials: [
        {
            _id: '6124bbd2f8eacfa2ca662f35',
            userId: '6124bbd2f8eacfa2ca662f29',
            testimonial: 'Amazing property',
            propertyId: '6124bbd2f8eacfa2ca662f34',
            user: {
                _id: '6124bbd2f8eacfa2ca662f29',
                firstName: 'John',
                lastName: 'Doe',
                email: 'jd@mail.com',
            }
        },
        {
            _id: '6124bbd2f8eacfa2ca662f35',
            userId: '6124bbd2f8eacfa2ca662f27',
            testimonial: 'Worth the price',
            propertyId: '6124bbd2f8eacfa2ca662f34',
            user: {
                _id: '6124bbd2f8eacfa2ca662f27',
                firstName: 'Sam',
                lastName: 'Ben',
                email: 'sb@mail.com',
            }
        }
    ]
}

您可以将 $lookup 阶段放在管道中,

  • $lookup 与用户合集
  • $addFields, $arrayElemAt 从上面的用户查找结果中获取第一个元素
Property.aggregate([
  { $match: { _id: ObjectId(propertyId) } },
  {
    $lookup: {
      from: "propertytestimonials",
      let: { propPropertyId: "$_id" },
      pipeline: [
        {
          $match: {
            $expr: { $eq: ["$propertyId", "$$propPropertyId"] }
          }
        },
        {
          $lookup: {
            from: "users",
            localField: "userId",
            foreignField: "_id",
            as: "user"
          }
        },
        {
          $addFields: {
            user: { $arrayElemAt: ["$user", 0] }
          }
        }
      ],
      as: "testimonials"
    }
  }
])

Playground