Node.js 在mongodb中加入两个集合

Node.js 在mongodb中加入两个集合,node.js,mongoose,aggregate-functions,Node.js,Mongoose,Aggregate Functions,我有单独的“评论”、“产品”和“用户”集合。“comments”集合包含文本、产品id和用户id。获取产品时,我希望结果中包含产品的详细信息以及用户的详细信息 我已经使用MongooseODM创建了模式。我正在使用聚合函数使用$lookup用注释填充产品 Product.aggregate([ { $match:{ _id:mongoose.Types.ObjectId(id) } }

我有单独的“评论”、“产品”和“用户”集合。“comments”集合包含文本、产品id和用户id。获取产品时,我希望结果中包含产品的详细信息以及用户的详细信息

我已经使用MongooseODM创建了模式。我正在使用聚合函数使用$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"
            }
        }
])
预期结果是

[
    {
        "_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"
                         },
                }

    }
]
[
    {
        "_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
                }
            ]
        }
    }
]
实际结果是

[
    {
        "_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"
                         },
                }

    }
]
[
    {
        "_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
                }
            ]
        }
    }
]

您对
用户的
$lookup
查询正在覆盖
注释
数组。它不像你想象的那样工作

您需要展开注释数组,然后运行用户的
$lookup
,然后按产品分组

编辑:我也用$group by code更新了查询。此外,您还可以在此处使用查询:


根据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
            }
          }
        }
      }
    ])

这样我得到了理想的结果。

既然您使用的是mongoose,那么您应该使用mongoose方式,即使用
填充
函数。尝试类似这样的
Product.find(id).populate('comments').populate('comments.user')
但我不确定嵌套用户。我认为如果产品模型包含对注释的引用,则populate会起作用,但在我的例子中,comments集合包含对产品的引用,因此,使用Comment.find({product.\u id:id}).populate('user')可以很容易地获取特定产品的注释,但在我的例子中,我希望一次获取所有产品以及特定用户的注释