我想汇总下面的集合(评论和帐户),但无法正确管理,因此我需要问你们。
当前评论集写在下面
{
lawyerId: { type: mongoose.Schema.Types.ObjectId },
reviews: [
{
userId: { type: mongoose.Schema.Types.ObjectId, unique: true },
message: { type: String },
rate: { type: Number },
createdAt: { type: Date, default: Date.now },
},
],
}
如果您推荐评论集可以像这样重构
{
lawyerId: { type: mongoose.Schema.Types.ObjectId },
userId: { type: mongoose.Schema.Types.ObjectId },
message: { type: String },
rate: { type: Number },
createdAt: { type: Date, default: Date.now },
}
帐户收集
{
_id: { type: mongoose.Schema.Types.ObjectId}
email: { type: String, unique: true },
firstName: { type: String },
lastName: { type: String },
},
获取评论的预期结果
{
averageRate: 3.2,
reviews: [
{
firstName: 'Jack',
lastName: 'Harden',
message: 'I dont like it',
rate: 2,
createdAt: '2020-01-01T14:58:23.330+00:00'
},
{
firstName: 'Takeshi',
lastName: 'San',
message: 'Thats nice',
rate: 5,
createdAt: '2020-03-02T10:45:10.120+00:00'
}
],
}
您应该可以使用aggregation来实现。
您可以查看实时demo here,使您可以运行此查询。
查询:
// Assuming we are searching for an lawyerId of 3
db.review.aggregate([
{
$match: {
lawyerId: 3
}
},
{
$lookup: {
from: "account",
localField: "userId",
foreignField: "_id",
as: "user"
}
},
{
$unwind: "$user"
},
{
$group: {
_id: "$lawyerId",
averageRate: {
$avg: "$rate"
},
reviews: {
$push: {
createdAt: "$createdAt",
firstName: "$user.firstName",
lastName: "$user.lastName",
message: "$message",
rate: "$rate"
}
}
}
},
{ // *******************************************
$project: { // *******************************************
_id: 0, // If you comment out/remove all of these lines
averageRate: 1, // then the return also contains the 'lawyerId',
reviews: 1 // as '_id', which I would find useful...
} // *******************************************
} // *******************************************
])
结果:
来自上面的查询,使用来自上面的数据集,产生以下结果:
[
{
"averageRate": 3.25,
"reviews": [
{
"createdAt": ISODate("2015-02-28T00:00:00Z"),
"firstName": "First",
"lastName": "Uno",
"message": "Message meh",
"rate": 3
},
{
"createdAt": ISODate("2015-02-28T00:00:00Z"),
"firstName": "Second",
"lastName": "Dos",
"message": "Message blah",
"rate": 4
},
{
"createdAt": ISODate("2015-02-28T00:00:00Z"),
"firstName": "First",
"lastName": "Uno",
"message": "Message foo",
"rate": 4
},
{
"createdAt": ISODate("2015-02-28T00:00:00Z"),
"firstName": "Third",
"lastName": "Tres",
"message": "Message bar",
"rate": 2
}
]
}
]
数据集:
在Mongo Playground中,您可以构建具有多个集合的数据库,这说明了数据结构:
db={ // <---- Database 'db'
"account": [ // <---- Collection 'account'
{
_id: 21,
email: "[email protected]",
firstName: "First",
lastName: "Uno"
},
{
_id: 22,
email: "[email protected]",
firstName: "Second",
lastName: "Dos"
},
{
_id: 23,
email: "[email protected]",
firstName: "Third",
lastName: "Tres"
}
],
"review": [ // <---- Collection 'review'
{
lawyerId: 3,
userId: 21,
message: "Message meh",
rate: 3,
createdAt: ISODate("2015-02-28T00:00:00Z")
},
{
lawyerId: 3,
userId: 22,
message: "Message blah",
rate: 4,
createdAt: ISODate("2015-02-28T00:00:00Z")
},
{
lawyerId: 3,
userId: 21,
message: "Message foo",
rate: 4,
createdAt: ISODate("2015-02-28T00:00:00Z")
},
{
lawyerId: 3,
userId: 23,
message: "Message bar",
rate: 2,
createdAt: ISODate("2015-02-28T00:00:00Z")
}
]
}
您可以尝试使用此管道从评论集中获取所有评论:
db.reviews.aggregate([
{
$lookup: {
from: "accounts",
localField: "userId",
foreignField: "_id",
as: "user"
}
},
{
$unwind: "$user"
},
{
$addFields: {
"firstName": "$user.firstName",
"lastName": "$user.lastName"
}
},
{
$group: {
"_id": null,
"average_rate": {
$avg: "$rate"
},
"reviews": {
$push: "$$ROOT"
}
}
},
{
$unset: [
"_id",
"reviews._id",
"reviews.user",
"reviews.userId",
"reviews.lawyerId"
]
}
])
结果:
[
{
"average_rate": 3.5,
"reviews": [
{
"createdAt": "Some Review Date",
"firstName": "Jack",
"lastName": "Harden",
"message": "I dont like it",
"rate": 2
},
{
"createdAt": "Some Review Date",
"firstName": "Takeshi",
"lastName": "San",
"message": "That's nice",
"rate": 5
}
]
}
]