lookup with condition in mongoose

ⅰ亾dé卋堺 提交于 2021-02-10 16:19:21

问题


I have two collections. articles and bookmarks.

articles

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

bookmarks

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

I want to join article with bookmark. if user bookmarked a article. what i have tried

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"
        }
    }
]);

but it will gives all bookmark for the article not only logged in user bookmark. so how can I add a condition.

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

回答1:


You can use $lookup with pipeline starting from MongoDB v3.6,

  • let to pass localField _id as model_id variable, you can use the field inside lookup pipeline using $$ reference,
  • pipeline to put $match stage and match your required conditions and user_id condition
  {
    $lookup: {
      from: "bookmarks",
      let: { model_id: "$_id" },
      pipeline: [
        {
          $match: {
            $expr: { $eq: ["$$model_id", "$model_id"] },
            user_id: objectId(req.user._id)
          }
        }
      ],
      as: "bookmarks"
    }
  }

Other option for MongoDB v3.4,

  • $filter to iterate loop of bookmarks and get filtered bookmarks on the base of condition
  {
    $lookup: {
      from: "bookmarks",
      localField: "_id",
      foreignField: "model_id",
      as: "bookmarks"
    }
  },
  {
    $addFields: {
      bookmarks: {
        $filter: {
          input: "$bookmarks",
          cond: { $eq: ["$$this.user_id", objectId(req.user._id)] }
        }
      }
    }
  }



回答2:


You can have nested pipeline inside $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"
    }
  }
])

Here's a working playground



来源:https://stackoverflow.com/questions/65518294/lookup-with-condition-in-mongoose

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!