我有一个评级模型,其中包含书籍和评级值。我想获得数据库中每本书的所有评级数(评级从1到5不等)。
我的架构看起来像 -
{
"_id": ObjectId("57e112312a52fe257e5d1d5c"),
"book": ObjectId("57e111142a52fe257e5d1d42"),
"rating": 4
}
{
"_id": ObjectId("57e7a002420d22d6106a4715"),
"book": ObjectId("57e111142a52fe257e5d1d42"),
"rating": 5
}
{
"_id": ObjectId("57e7a4cd98bfdb5a11962d54"),
"book": ObjectId("57e111142a52fe257e5d17676"),
"rating": 5
}
{
"_id": ObjectId("57e7a4cd98bfdb5a11962d54"),
"book": ObjectId("57e111142a52fe257e5d17676"),
"rating": 1
}
目前,我只能达到这一点,我可以获得每本书的评级,但它没有明确指定评级值。
这是我当前的查询 -
db.ratings.aggregate([
{$match: {book: {$in: [ObjectId("57e111142a52fe257e5d1d42"), ObjectId('57e6bef7cad79fa38555c643')]}}},
{$group: {_id: {book: "$book", value: "$value"} } },
{$group: {_id: "$_id.book", total: {$sum: 1}}},
])
输出是这个 -
{
"result": [
{
"_id": ObjectId("57e6bef7cad79fa38555c643"),
"total": 2
},
{
"_id": ObjectId("57e111142a52fe257e5d1d42"),
"total": 2
}
],
"ok": 1
}
但是,我想联合所有文件并获得rating
字段的每个值的评分计数结果,如下所示。重点是我只想要每本书的每个值的评级计数。
{
result: [
{
_id: "57e111142a52fe257e5d17676",
5_star_ratings: 1,
4_star_ratings: 3,
3_star_ratings: 4,
2_star_ratings: 1,
1_star_ratings: 0,
},
{
_id: "57e111142a52fe257e5d1d42",
5_star_ratings: 10,
4_star_ratings: 13,
3_star_ratings: 7,
2_star_ratings: 8,
1_star_ratings: 19,
}
.
.
.
.
]
}
我该怎么做?
答案 0 :(得分:2)
完成任务需要 $cond
管道,该管道使用 $sum
$cond
运算符>累加器操作员。 $sum
运算符将根据其第一个参数(if)计算逻辑条件,然后返回第二个参数,其中评估为true(然后)或第三个参数,其中false(else) 。这会将true / false逻辑转换为分别输入 {{3}} 的1和0数值:
$group
作为结果操作,您可能希望运行以下聚合管道:
{
"$sum": {
"$cond": [ { "$eq": [ "$rating", 1 ] }, 1, 0 ]
}
}
对于比上述方法执行速度更快的更灵活,性能更好的方法,请考虑运行替代管道,如下所示
var pipeline = [
{
"$match": {
"book": {
"$in": [
ObjectId("57e111142a52fe257e5d1d42"),
ObjectId('57e6bef7cad79fa38555c643')
]
}
}
},
{
"$group": {
"_id": "$book",
"5_star_ratings": {
"$sum": {
"$cond": [ { "$eq": [ "$rating", 5 ] }, 1, 0 ]
}
},
"4_star_ratings": {
"$sum": {
"$cond": [ { "$eq": [ "$rating", 4 ] }, 1, 0 ]
}
},
"3_star_ratings": {
"$sum": {
"$cond": [ { "$eq": [ "$rating", 3 ] }, 1, 0 ]
}
},
"2_star_ratings": {
"$sum": {
"$cond": [ { "$eq": [ "$rating", 2 ] }, 1, 0 ]
}
},
"1_star_ratings": {
"$sum": {
"$cond": [ { "$eq": [ "$rating", 1 ] }, 1, 0 ]
}
}
}
},
]
db.ratings.aggregate(pipeline)