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

时间:2019-06-19 15:20:37

标签: mongodb mongoose aggregation-framework lookup aggregation

我正在尝试向我的网站添加 like 功能。我使用以下架构收集了顶赞。我使用自定义_id以避免创建额外的索引。

{
  _id: {
    postId: ObjectId,
    userId: ObjectId
  }
}

我的服务器上有一条路由,该路由使用MongoDB 集合搜索帖子集合。我正在尝试向当前管道添加一个 $ lookup 阶段,以添加一个 like 属性,其类型为 Boolean ,指示是否没有该帖子已被用户喜欢。这是 $ lookup 阶段不起作用的步骤( liked 总是返回一个空数组,即使有相应的like文档也是如此):

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

我认为问题在于变量实际上没有保存我期望它们的值。有什么办法解决这个问题?另外,如果您知道一种更简单的实现方法,也希望与我分享。

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

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

1 个答案:

答案 0 :(得分:1)

相反。如果您正在$lookup集合上运行likes,则let部分的目标是定义引用正在运行聚合的集合的变量。另一方面,您可以使用likes内的单个美元符号引用pipeline集合中定义的字段。试试:

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

编辑:请看一下docs

  


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

     

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