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

Posted

技术标签:

【中文标题】使用管道中的数组中的对象值执行 $lookup【英文标题】:Perform $lookup with object value in array from pipeline 【发布时间】:2021-10-24 13:43:03 【问题描述】:

所以我有 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',
            
        
    ]

【问题讨论】:

添加属性架构 向我们展示所有 3 个集合中的示例文档 【参考方案1】:

您可以将$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

【讨论】:

以上是关于使用管道中的数组中的对象值执行 $lookup的主要内容,如果未能解决你的问题,请参考以下文章

$lookup 中的其他连接条件严重降低了性能(使用管道)

Mongodb 聚合管道限制 $lookup 字段

Mongo:管道中的 $exists $lookup 未按预期工作

使用 $cond 切换更新管道中的嵌套数组值

基于通过 $lookup 检索的字段的多阶段聚合管道匹配数据

MongoDB——聚合管道之$lookup操作