简体   繁体   English

在mongodb中加入两个集合

[英]Joining two collections in mongodb

I have separate collections for 'comments','products' and 'users'. 我为“评论”,“产品”和“用户”提供了单独的集合。 The 'comments' collection contains text, product_id and user_id. “评论”集合包含文本,product_id和user_id。 When a product is fetched I want the details of product along with details of the user in the result. 提取产品时,我需要产品的详细信息以及结果中的用户详细信息。

I have created schema using mongoose odm. 我已经使用猫鼬odm创建了架构。 I am using aggregate function to populate the product with comments using $lookup. 我正在使用聚合函数使用$ lookup在产品中添加注释。

Product.aggregate([
        {
            $match:{
                _id:mongoose.Types.ObjectId(id)
            }
        },
        {
            $lookup: {
                from: "comments",
                localField: "_id",
                foreignField: "product",
                as: "comments"
            }
        },
        {
            $match:{
                "comments.product":mongoose.Types.ObjectId(id)
            }
        },
        {
            $lookup: {
                from: "users",
                localField: "comments.user._id",
                foreignField: "user",
                as: "comments.user"
            }
        }
])

expected result is 预期结果是

[
    {
        "_id": "5cc9441feed4c258881c99cd",
        "title": "Batman",
        "imageUrl": "images\\1556694047310_Batman.jpg",
        "price": 555,
        "description": "The dark knight",
        "user": "5cbca36d4acc5d538c209014",
        "__v": 2,
        "comments": [
                { 
                  "_id": "5cc947125c69600d58c1be05",
                  "date": "2019-05-01T07:12:42.229Z",
                  "text": "This product is very nice",
                  "user":{
                          "_id": "5cbca36d4acc5d538c209014",
                          "name": "Clark Kent"
                         }
                },
                {
                  "_id": "5cc96eb4b2834d43f8a24470",
                  "date": "2019-05-01T09:46:34.774Z",
                  "text": "Anyone can be Batman",
                  "user":{
                          "_id": "5cbca5504acc5d538c209015",
                          "name": "Bruce Wayne"
                         },
                }

    }
]

actual result is 实际结果是

[
    {
        "_id": "5cc9441feed4c258881c99cd",
        "title": "Batman",
        "imageUrl": "images\\1556694047310_Batman.jpg",
        "price": 555,
        "description": "The dark knight",
        "user": "5cbca36d4acc5d538c209014",
        "__v": 2,
        "comments": {
            "user": [
                {
                    "_id": "5cbca5504acc5d538c209015",
                    "name": "Bruce Wayne",
                    "email": "batman@gotham.com",
                    "password": "$2a$12$L.t/nBXq/xlic25Y0a884uGxjlimuNH/tcmWLg.sNkcjJ/C40Q14m",
                    "contactNumber": 9999999999,
                    "address": "Somewhere in Gotham",
                    "__v": 0
                },
                {
                    "_id": "5cbca7334acc5d538c209016",
                    "name": "Superman",
                    "email": "superman@metro.com",
                    "password": "$2a$12$mrogzC1Am86b0DnvTzosm.qfu38Ue7RqSNcnVSoCR55PtmLddeZv.",
                    "contactNumber": 9999999999,
                    "address": "Somewhere in metropolis",
                    "__v": 0
                },
                {
                    "_id": "5cbca7e54acc5d538c209017",
                    "name": "Wonder Woman",
                    "email": "ww@amazon.com",
                    "password": "$2a$12$Vt9XZUyOTULvel5zNAsMLeoMi3HlaGJJZN7OH2XkWuoAiZtDIGaMq",
                    "contactNumber": 9999999999,
                    "address": "Somewhere in Amazon",
                    "__v": 0
                },
                {
                    "_id": "5cbe192934ae2944c8704a5a",
                    "name": "Barry Allen",
                    "email": "barry@flash.com",
                    "password": "$2a$12$k73Wp1HTMv/MhUV3BOok3OSh.nnLq3vWG1Qz9ZTO7iB7saFlxhLjW",
                    "contactNumber": 9999999999,
                    "address": "Somewhere in Central City",
                    "__v": 0
                }
            ]
        }
    }
]

Your $lookup query of users is overwriting the comments array. 您对users $lookup查询正在覆盖comments数组。 Its not working as you think it'll. 它不起作用,如您所愿。

You need to unwind the comments array and then run that $lookup of users and then group by the products. 您需要展开注释数组,然后运行该$lookup用户,然后按产品分组。

Edit: I have updated the query with $group by code too. 编辑:我也用$ group通过代码更新了查询。 Also you can playa around with the query here: https://mongoplayground.net/p/2EA-Glz8Hrm 您也可以在此处查询以下内容: https : //mongoplayground.net/p/2EA-Glz8Hrm

Product.aggregate([
  {
    $match: {
      _id: "5cc9441feed4c258881c99cd"
    }
  },
  {
    $lookup: {
      from: "comments",
      localField: "_id",
      foreignField: "product",
      as: "comments"
    }
  },
  {
    $unwind: "$comments"
  },
  {
    $lookup: {
      from: "users",
      localField: "comments.user",
      foreignField: "_id",
      as: "comments.user"
    }
  },
  {
    $unwind: "$comments.user"
  },
  {
    $group: {
      _id: "$_id",
      // add other fields you want to include
      comments: {
        $addToSet: "$comments"
      }
    }
  },

])

As suggested by Hamza, I made following changes to my query 根据Hamza的建议,我对查询进行了以下更改

Product.aggregate([
      {
        $match: {
          _id: mongoose.Types.ObjectId(id)
        }
      },
      {
        $lookup: {
          from: "comments",
          localField: "_id", //field from input document
          foreignField: "product", // field from documents of the 'from' collection
          as: "comments"
        }
      },
      {
        $unwind: "$comments"
      },
      {
        $lookup: {
          from: "users",
          localField: "comments.user", //field from input document
          foreignField: "_id", // field from documents of the 'from' collection
          as: "comments.user"
        }
      },
      {
        $unwind: "$comments.user"
      },
      {
        $group: {
          _id: "$_id",
          title: { $first: "$title" }, // $first returns the first expression of the document it encounters, ex. first title
          price: { $first: "$price" },
          imageUrl: { $first: "$imageUrl" },
          description: { $first: "$description" },
          rating: { $first: "$rating" },
          comments: {
            $addToSet: "$comments" // group comments and create an array
          }
        }
      },
      {
        $project: {
          _id: 1,
          title: 1,
          price: 1,
          imageUrl: 1,
          description: 1,
          rating: 1,
          comments: {
            _id: 1,
            text: 1,
            date: 1,
            user: {
              _id: 1,
              name: 1
            }
          }
        }
      }
    ])

With this I got the desired result. 这样我得到了预期的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM