2013-12-18 2 views
2

Вот структура документа в MongoDB:MongoDB: Вычислить среднее значение все поля конкретного документа, которые встраиваются в виде списка в документе

{ 
    "_id" : NumberLong(1), 
    "averageRating" : 2.5, 
    "date" : ISODate("2013-11-12T02:15:14.448Z"), 
    "filledBy" : "Degroote, Fred", 
    "results" : [ 
     { 
      "answer" : "Very caring doctor. I am happy", 
      "name" : "comment", 
      "type" : "string" 
     }, 
     { 
      "answer" : "4", 
      "name" : "premises", 
      "type" : "integer" 
     }, 
     { 
      "answer" : "5", 
      "name" : "staff", 
      "type" : "integer" 
     }, 
     { 
      "answer" : "0", 
      "name" : "provider", 
      "type" : "integer" 
     }, 
     { 
      "answer" : "1", 
      "name" : "care", 
      "type" : "integer" 
     } 
    ], 
    "tenantId" : NumberLong(2), 
    "token" : "38ae01f0-1203-4d10-9ff1-7c9fad1790cc", 
    "version" : NumberLong(0) 
} 

Нам необходимо вычислить среднее значение баллов ответить не соответствует имени результата «сотрудники 'в результатах всех документов, имеющих значение tenantId 2.

запрос MongoDB, который мы написали:

> db.surveyResults.aggregate({$match: {'tenantId': 2}}, {$unwind: '$results'}, {$match: {'results.type':'integer'}},{$group: {_id: '$results.name', averageSatisfaction: {$avg: '$results.answer'}}}) 

Но проблема в приведенном выше запросе MongoDB является что ответ на поле имеет строку типа. Есть ли способ решить эту проблему без изменения типа ответа на поле?

ответ

1

Я думаю, что это некрасиво запрос, но это работает:

db.surveyResults.aggregate(
    {$match: {'tenantId': 2}}, 
    {$unwind: '$results'}, 
    {$match: {'results.type':'integer'}}, 
    {$project:{ 
     "results.answer":1, 
     "results.name":1, 
     one:{$cond:[{$eq:["$results.answer","1"]},1,0]}, 
     two:{$cond:[{$eq:["$results.answer","2"]},2,0]}, 
     three:{$cond:[{$eq:["$results.answer","3"]},3,0]}, 
     four:{$cond:[{$eq:["$results.answer","4"]},4,0]}, 
     five:{$cond:[{$eq:["$results.answer","5"]},5,0]}, 
     six:{$cond:[{$eq:["$results.answer","6"]},6,0]}, 
     seven:{$cond:[{$eq:["$results.answer","7"]},7,0]}, 
     eight:{$cond:[{$eq:["$results.answer","8"]},8,0]}, 
     nine:{$cond:[{$eq:["$results.answer","9"]},9,0]}, 
     } 
    }, 
    {$project: { 
     "results.name":1,   
     sum:{$add:["$one","$two","$three","$four","$five","$six","$seven","$eight","$nine"]}   
    }}, 
    {$group: 
     {_id: '$results.name', averageSatisfaction: {$avg: '$sum'}} 


     } 

     ) 

Во всяком случае, лучшим вариантом будет использовать целые числа, как целые числа.

+1

Мы нашли альтернативу, не вычисляя среднее значение. Вместо этого группируйте все ответы по имени и затем вычисляйте среднее значение извне. Вот запрос, который мы используем: > db.surveyResults.aggregate ({$ match: {'tenantId': 2}}, {$ project: {'results': 1}}, {$ unwind: '$ results' }, {$ match: {'results.type': 'integer'}}, {$ group: {_id: '$ results.name', ответы: {$ push: '$ results.answer'}}}) –

+0

Рад, что вы нашли обходной путь. Может быть, мое решение может помочь кому-то другому. – rubenfa

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