【问题标题】:lookup with condition in mongoose在猫鼬中查找条件
【发布时间】:2021-04-07 15:01:47
【问题描述】:

我有两个系列。文章和书签。

文章

{
    _id: "5faa889ade5e0a6326a873d3",
    name: "article 1"
},
{
    _id: "5faa889ade5e0a6326a873d",
    name: "article 2"
}

书签

{
    _id: "5faa889ade5e0a6326a873d1",
    user_id: "5fc7b50da483a66a86aa7e9e",
    model_id: "5faa889ade5e0a6326a873d3"
}

我想加入带有书签的文章。如果用户为文章添加书签。 我尝试过的

const aggregate = await Articles.aggregate([{
        $lookup: {
            from: "categories",  
            localField: "category_id",
            foreignField: "_id",
            as: "category_id"
        }
    },
    {

        $lookup: {
            from: "bookmarks",  
            localField: "_id",
            foreignField: "model_id",
            as: "bookmarks"
        }
    }
]);

但它会为文章提供所有书签,而不仅仅是登录用户书签。那么如何添加条件。

{ "user_id": objectId(req.user._id) } // logged user id

【问题讨论】:

    标签: mongodb mongoose aggregation-framework


    【解决方案1】:

    你可以使用$lookup with pipeline从MongoDB v3.6开始

    • 让 localField _id 作为 model_id 变量传递,您可以使用 $$ 引用在查找管道中使用该字段,
    • 管道放置$match 阶段并匹配您所需的条件和user_id 条件
      {
        $lookup: {
          from: "bookmarks",
          let: { model_id: "$_id" },
          pipeline: [
            {
              $match: {
                $expr: { $eq: ["$$model_id", "$model_id"] },
                user_id: objectId(req.user._id)
              }
            }
          ],
          as: "bookmarks"
        }
      }
    

    MongoDB v3.4的其他选项,

    • $filter 迭代 bookmarks 的循环并根据条件获取过滤后的书签
      {
        $lookup: {
          from: "bookmarks",
          localField: "_id",
          foreignField: "model_id",
          as: "bookmarks"
        }
      },
      {
        $addFields: {
          bookmarks: {
            $filter: {
              input: "$bookmarks",
              cond: { $eq: ["$$this.user_id", objectId(req.user._id)] }
            }
          }
        }
      }
    

    【讨论】:

    • 我收到错误 MongoError: arguments to $lookup must be strings, let: { model_id: "$_id" } is type object
    • 你能确认你的mongodb版本吗?可能是您的 mongodb 版本低于 3.6,如果从 v3.6 支持此功能
    • 好的,知道了。现在是 3.4。有什么选择
    • 我认为不,您可以在正常查找阶段后进行过滤,使用该选项更新我的答案。
    【解决方案2】:

    您可以在$lookup 中嵌套管道,

    db.articles.aggregate([
      {
        $lookup: {
          from: "bookmarks",
          let: {
            article_id: "$_id"
          },
          pipeline: [
            {
              $match: {
                $expr: {
                  $and: [
                    {
                      $eq: [
                        "$model_id",
                        "$$article_id"
                      ]
                    },
                    {
                      $eq: [
                        "$user_id",
                        "5fc7b50da483a66a86aa7e9a"
                      ]
                    }
                  ]
                }
              }
            }
          ],
          as: "bookmarks"
        }
      }
    ])
    

    这是一个有效的playground

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-10
      • 2020-09-12
      • 2017-04-06
      • 2019-07-20
      • 2016-05-14
      相关资源
      最近更新 更多