$avg в агрегации mongodb

Документ выглядит так:

   {
    "_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"} оценка равна 30, для документа { "NAME" : "asd"} и {evaluator_id: "e2"} оценка равна 0< /strong> для { "ИМЯ" : "asd" }. В этом случае я хочу, чтобы AVG_SCORE был только 30 (не (30 + 0)/2 = 15).

Возможно ли это через агрегацию??

Может ли кто-нибудь помочь мне.


person manojpt    schedule 12.03.2015    source источник


Ответы (1)


Это возможно, если поместить $match между конвейеры агрегации $unwind и $group, чтобы сначала отфильтровать массивы, соответствующие указанному условию, для включения в вычисление среднего значения, то есть массив оценок, где полученная оценка не равна 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
}
person chridam    schedule 12.03.2015
comment
Еще один случай: если и e1, и e2 дали оценку 0, NAME : asd будет пропущено в выводе. Но мне нужно (0 + 0)/2 = 0. Означает, если обе оценки равны 0, среднее значение должно быть равно 0 и если одна из оценок › 0, avg = (оценка, которая равна › 0). - person manojpt; 13.03.2015