在产品集合中保存评论引用将导致每次对该文档进行新评论时更新产品文档。并且产品会有很多其他的领域,所以没有必要让它有更多的领域。
我会建议家长参考这里。产品集合中不会有评论参考,但我们会将产品参考保留在评论集合中。当对产品进行评论时,我们只需要在评论集合中进行简单的插入即可。
我们还需要考虑对产品进行评论的用户。所以我们需要在评论集合中保留一个用户参考。
让我展示这些集合的一些示例文档:
产品:
{
"_id" : ObjectId("5e4bdffb09d2675c3cdf8371"),
"name" : "Product1",
"price" : 1
}
用户:
{
"_id" : ObjectId("5e4bdfa809d2675c3cdf8370"),
"username" : "User1",
}
评论:(用户 1 对 Product1 进行了评论)
{
"_id": ObjectId("5e4be86809d2675c3cdf8387"),
"reviewDate": ISODate("2020-02-18T15:51:22.584+03:00"),
"product": ObjectId("5e4bdffb09d2675c3cdf8371"),
"user": ObjectId("5e4be85d09d2675c3cdf8386"),
"score": 5
}
我们可以使用 mongodb 聚合框架在一个数据库访问中读取产品信息及其评论和评论的用户。所以这不是什么大问题。
例如:Playground
db.products.aggregate([
{
$match: {
_id: ObjectId("5e4bdffb09d2675c3cdf8371")
}
},
{
$lookup: {
from: "reviews",
localField: "_id",
foreignField: "product",
as: "reviews"
}
},
{
$unwind: "$reviews"
},
{
$sort: {
"reviews.reviewDate": -1
}
},
{
$lookup: {
from: "users",
localField: "reviews.user",
foreignField: "_id",
as: "user"
}
},
{
$addFields: {
"reviews.user": {
$arrayElemAt: [
"$user",
0
]
}
}
},
{
$project: {
user: 0
}
},
{
$group: {
_id: "$_id",
reviews: {
"$push": "$reviews"
},
"doc": {
"$first": "$$ROOT"
}
}
},
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
"$doc",
{
"reviews": "$reviews"
}
]
}
}
}
])
这将通过以下方式给出结果:
[
{
"_id": ObjectId("5e4bdffb09d2675c3cdf8371"),
"name": "Product1",
"price": 1,
"reviews": [
{
"_id": ObjectId("5e4be83b09d2675c3cdf8381"),
"product": ObjectId("5e4bdffb09d2675c3cdf8371"),
"reviewDate": ISODate("2020-02-18T16:15:22.584Z"),
"score": 2,
"user": {
"_id": ObjectId("5e4be83009d2675c3cdf8380"),
"username": "User8"
}
},
{
"_id": ObjectId("5e4be09709d2675c3cdf8375"),
"product": ObjectId("5e4bdffb09d2675c3cdf8371"),
"reviewDate": ISODate("2020-02-18T15:02:22.584Z"),
"score": 4,
"user": {
"_id": ObjectId("5e4be08b09d2675c3cdf8374"),
"username": "User2"
}
},
{
"_id": ObjectId("5e4be84b09d2675c3cdf8383"),
"product": ObjectId("5e4bdffb09d2675c3cdf8371"),
"reviewDate": ISODate("2020-02-18T14:08:22.584Z"),
"score": 3,
"user": {
"_id": ObjectId("5e4be84109d2675c3cdf8382"),
"username": "User9"
}
},
...
]
}
]
这样,当您打开产品详细信息页面的 GET api 时,这将包含您需要的所有信息。