mongodb 聚合中的 $avg
$avg in mongodb aggregation
文档看起来像这样:
{
"_id" : ObjectId("361de42f1938e89b179dda42"),
"user_id" : "u1",
"evaluator_id" : "e1",
"candidate_id" : ObjectId("54f65356294160421ead3ca1"),
"OVERALL_SCORE" : 150,
"SCORES" : [
{ "NAME" : "asd", "OBTAINED_SCORE" : 30}, { "NAME" : "acd", "OBTAINED_SCORE" : 36}
]
}
聚合函数:
db.coll.aggregate([ {$unwind:"$SCORES"}, {$group : { _id : { user_id : "$user_id", evaluator_id : "$evaluator_id"}, AVG_SCORE : { $avg : "$SCORES.OBTAINED_SCORE" }}} ])
假设有两个文档相同"user_id"(比如u1)和不同"evaluator_id"(说 e1 和 e2)。
例如:
1) 平均值将像这样计算 ((30 + 20) / 2 = 25)。这对我有用。
2) 但对于 { evaluator_id : "e1" } 文档,score 是 30 for { "NAME" : "asd" } 和 { evaluator_id : "e2" } 文档,{ "NAME" : "asd" } 的 分数为 0。在这种情况下,我希望 AVG_SCORE 仅为 30(不是 (30 + 0) / 2 = 15).
是否可以通过聚合实现?
谁能帮帮我
可以通过在$unwind
和$group
聚合管道之间放置一个$match
来首先过滤符合指定条件的数组包括在平均计算中,即获得的分数不等于 0 的分数数组 "SCORES.OBTAINED_SCORE" : { $ne : 0 }
db.coll.aggregate([
{
$unwind: "$SCORES"
},
{
$match : {
"SCORES.OBTAINED_SCORE" : { $ne : 0 }
}
},
{
$group : {
_id : {
user_id : "$user_id",
evaluator_id : "$evaluator_id"
},
AVG_SCORE : {
$avg : "$SCORES.OBTAINED_SCORE"
}
}
}
])
例如这个文档的聚合结果:
{
"_id" : ObjectId("5500aaeaa7ef65c7460fa3d9"),
"user_id" : "u1",
"evaluator_id" : "e1",
"candidate_id" : ObjectId("54f65356294160421ead3ca1"),
"OVERALL_SCORE" : 150,
"SCORES" : [
{
"NAME" : "asd",
"OBTAINED_SCORE" : 0
},
{
"NAME" : "acd",
"OBTAINED_SCORE" : 36
}
]
}
将产生:
{
"result" : [
{
"_id" : {
"user_id" : "u1",
"evaluator_id" : "e1"
},
"AVG_SCORE" : 36
}
],
"ok" : 1
}
文档看起来像这样:
{
"_id" : ObjectId("361de42f1938e89b179dda42"),
"user_id" : "u1",
"evaluator_id" : "e1",
"candidate_id" : ObjectId("54f65356294160421ead3ca1"),
"OVERALL_SCORE" : 150,
"SCORES" : [
{ "NAME" : "asd", "OBTAINED_SCORE" : 30}, { "NAME" : "acd", "OBTAINED_SCORE" : 36}
]
}
聚合函数:
db.coll.aggregate([ {$unwind:"$SCORES"}, {$group : { _id : { user_id : "$user_id", evaluator_id : "$evaluator_id"}, AVG_SCORE : { $avg : "$SCORES.OBTAINED_SCORE" }}} ])
假设有两个文档相同"user_id"(比如u1)和不同"evaluator_id"(说 e1 和 e2)。
例如:
1) 平均值将像这样计算 ((30 + 20) / 2 = 25)。这对我有用。
2) 但对于 { evaluator_id : "e1" } 文档,score 是 30 for { "NAME" : "asd" } 和 { evaluator_id : "e2" } 文档,{ "NAME" : "asd" } 的 分数为 0。在这种情况下,我希望 AVG_SCORE 仅为 30(不是 (30 + 0) / 2 = 15).
是否可以通过聚合实现?
谁能帮帮我
可以通过在$unwind
和$group
聚合管道之间放置一个$match
来首先过滤符合指定条件的数组包括在平均计算中,即获得的分数不等于 0 的分数数组 "SCORES.OBTAINED_SCORE" : { $ne : 0 }
db.coll.aggregate([
{
$unwind: "$SCORES"
},
{
$match : {
"SCORES.OBTAINED_SCORE" : { $ne : 0 }
}
},
{
$group : {
_id : {
user_id : "$user_id",
evaluator_id : "$evaluator_id"
},
AVG_SCORE : {
$avg : "$SCORES.OBTAINED_SCORE"
}
}
}
])
例如这个文档的聚合结果:
{
"_id" : ObjectId("5500aaeaa7ef65c7460fa3d9"),
"user_id" : "u1",
"evaluator_id" : "e1",
"candidate_id" : ObjectId("54f65356294160421ead3ca1"),
"OVERALL_SCORE" : 150,
"SCORES" : [
{
"NAME" : "asd",
"OBTAINED_SCORE" : 0
},
{
"NAME" : "acd",
"OBTAINED_SCORE" : 36
}
]
}
将产生:
{
"result" : [
{
"_id" : {
"user_id" : "u1",
"evaluator_id" : "e1"
},
"AVG_SCORE" : 36
}
],
"ok" : 1
}