2014-11-23 2 views
1

У меня есть коллекция документов (объявления) с поддокументами (Salary), как это:MongoDB: вычислить среднее значение для документа и затем сделать то же самое по всей коллекции

{ 
    _id: ObjectId("zzz"), 
    sphere: ObjectId("xxx"), 
    region: ObjectId("yyy"), 
    salary: { 
     start: 10000, 
     end: 50000 
    } 
} 

И я хочу, чтобы рассчитать среднюю зарплату через какой-то регион & сфера для всей коллекции. Я создал запрос для этого, он работает, но он заботится только о начальной стоимости зарплаты.

db.offer.aggregate(
    [ 
     {$match: 
      {$and: [ 
       {"salary.start": {$gt: 0}}, 
       {region: ObjectId("xxx")}, 
       {sphere: ObjectId("yyy")} 
      ]} 
     }, 
     {$group: {_id: null, avg: {$avg: "$salary.start"}}} 
    ] 
) 

Но во-первых, я хочу, чтобы вычислить насчитайте зарплату (начало & конца) предложений. Как я могу это сделать?

Обновление.

Если в ваших данных может отсутствовать значение «зарплата.end», вам нужно добавить еще одну итерацию «$ project», чтобы заменить отсутствующую «зарплату» на существующую «зарплату.старт». В противном случае результат средней функции будет вычисляться неправильно из-за игнорирования документов с отсутствием значений «зарплата.end».

db.offer.aggregate([ 
     {$match: 
      {$and: [ 
       {"salary.start": {$gt: 0}}, 
       {"region": ObjectId("xxx")}, 
       {"sphere": ObjectId("yyy")} 
      ]} 
     }, 
     {$project:{"_id":1, 
        "sphere":1, 
        "region":1, 
        "salary.start":1, 
        "salary.end":1, 
        "salary.end": {$ifNull: ["$salary.end", "$salary.start"]} 
        } 
     }, 
     {$project:{"_id":1, 
        "sphere":1, 
        "region":1, 
        "avg_salary":{$divide:[ 
              {$add:["$salary.start","$salary.end"]} 
              ,2 
              ]}}}, 
     {$group:{"_id":{"sphere":"$sphere","region":"$region"}, 
       "avg":{$avg:"$avg_salary"}}} 
]) 

ответ

0

как вы агрегировать должен быть изменен:

  • Match требуемая область, сфера, где зарплата> 0.
  • Project дополнительное поле для каждого предложения, которое держит в среднем начало и конец.
  • Теперь group вместе записи с той же самой области и сферы, и применить оператор $avg агрегации на avg_salary для каждого предложения в этой группе, чтобы получить среднюю зарплату.

Кодекс:

db.offer.aggregate([ 
     {$match: 
      {$and: [ 
       {"salary.start": {$gt: 0}}, 
       {"region": ObjectId("xxx")}, 
       {"sphere": ObjectId("yyy")} 
      ]} 
     }, 
     {$project:{"_id":1, 
        "sphere":1, 
        "region":1, 
        "avg_salary":{$divide:[ 
              {$add:["$salary.start","$salary.end"]} 
              ,2 
              ]}}}, 
     {$group:{"_id":{"sphere":"$sphere","region":"$region"}, 
       "avg":{$avg:"$avg_salary"}}} 
]) 
+0

Спасибо! Оно работает. – Ilya

Смежные вопросы