使用 $lookup 和 let 和管道在 MongoDB 中声明变量

Ami*_*k88 2 lookup aggregation mongoose mongodb aggregation-framework

我正在尝试向我的网站添加类似功能。我用以下模式制作了一个喜欢的集合。我使用自定义 _id 来避免创建额外的索引。

{
  _id: {
    postId: ObjectId,
    userId: ObjectId
  }
}
Run Code Online (Sandbox Code Playgroud)

我的服务器上有一个路由,它使用 MongoDB聚合搜索帖子集合。我正在尝试向当前管道添加一个$lookup阶段,以便添加一个带有布尔类型的喜欢属性,指示用户是否喜欢该帖子。这里的$查找未工作阶段(喜欢返回一个空数组全偶的时候有一个相应的像文件):

{
  $lookup: {
    from: 'likes',
    let: { likedPostId: '$_id.postId', likerUserId: '$_id.userId' },
    pipeline: [
      { $match:
        { $expr:
          { $and:
            [
              { $eq: [
                '$$likerUserId',
                  ObjectId('12345')
              ]},
              { $eq: [
                  '$$likedPostId',
                  '$_id'
              ]}
            ]
          }
        }
      }
    }
  ],
  as: 'liked'
  }
}
Run Code Online (Sandbox Code Playgroud)

我认为问题在于变量实际上并不包含我期望的值。有没有办法解决这个问题?另外,如果您知道一种更简单的方法来实现这一点,如果您与我分享,我将不胜感激。

我尝试比较两个相同的ObjectId()实例以确保可以使用$eq运算符比较ObjectId实例。还尝试在不同的嵌套字段上定义嵌套变量,例如上面代码片段中的变量。这个问题唯一不同的是,我试图将属性拉到_id 字段之外。

PS 我知道喜欢的属性是一个Array而不是Boolean。但我正在考虑在下一阶段将其转换为布尔值。但这不是现在的问题。

mic*_*ckl 9

正好相反。如果您$lookuplikes集合上运行,那么let部分的目标是定义引用您正在运行聚合的集合的变量。另一方面,您可以likes使用pipeline. 尝试:

{
    $lookup: {
        from: 'likes',
        let: { id: '$_id' },
        pipeline: [
            { $match:
                { $expr:
                { $and:
                    [
                    { $eq: [
                        '$_id.userId',
                        ObjectId('12345')
                    ]},
                    { $eq: [
                        '$_id.postId',
                        '$$id'
                    ]}
                    ]
                }
                }
            }
        ],
        as: 'liked'
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:请查看文档


可选。指定要在管道字段阶段中使用的变量。使用变量表达式访问从文档输入到 $lookup 阶段的字段。

管道无法直接访问输入文档字段。相反,首先为输入文档字段定义变量,然后在管道的各个阶段中引用变量。