Node.js 在mongodb中加入两个集合
我有单独的“评论”、“产品”和“用户”集合。“comments”集合包含文本、产品id和用户id。获取产品时,我希望结果中包含产品的详细信息以及用户的详细信息 我已经使用MongooseODM创建了模式。我正在使用聚合函数使用$lookup用注释填充产品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) } }
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')可以很容易地获取特定产品的注释,但在我的例子中,我希望一次获取所有产品以及特定用户的注释