2015-09-11 3 views
1

Учитывая некоторые данные, как это:Как суммировать в записи с помощью MongoDB агрегатных функций

[ 
    {issue: "taxes", resp: "agree"}, 
    {issue: "taxes", resp: "disagree"}, 
    {issue: "taxes", resp: "disagree"}, 
    {issue: "sexism", resp: "disagree"}, 
    {issue: "sexism", resp: "disagree"}, 
] 

Я хотел бы использовать Монго агрегатные функции, чтобы получить меня к выходу точно так:

{issue: "taxes", agree: 1, disagree: 2, tot: 3} 
{issue: "sexism", agree: 0, disagree: 2, tot: 2} 

Я попытался это:

db.responses.aggregate(
    [ 
     { 
     $group : { 
      _id : { issue: "$issue", resp: "$resp" }, 
      count: { $sum: 1 }, 
     } 
     }, 
    ] 
) 

Который получает меня близко, но не совсем:

"result" : [ 
    { 
     "_id" : { 
      "issue" : "racism", 
      "resp" : "agree" 
     }, 
     "count" : 3 
    }, 
    { 
     "_id" : { 
      "issue" : "racism", 
      "resp" : "disagree" 
     }, 
     "count" : 3 
    }, 

Я мог проанализировать данные, как только он вернется с петлей и некоторыми уродливыми счетчиками, и для объема данных, которые у меня есть, это будет неважно. Но мне любопытно и пытаться поправиться в агрегации Монго. Я думаю, мне нужен проект $ project, но я не могу понять это!

Мне также интересно узнать о масштабируемости этого, вплоть до ответов от 20 к до 50 тыс. Записей ответов или так, для типичной конфигурации монгонга. Мне было бы нелегко создать сводный документ и просто обновить итоговые значения для согласия/несогласия с входом пользователя. Результат, о котором я думаю, будет моим желаемым результатом плюс поле кандидата/etc для поиска. Может быть, это более монго-иш-способ делать вещи? Любые мысли оценили.

ответ

3

Tricky, но очень выполнимый. То, что вы в принципе нужно сделать, это сделать «условную сумму» вместо того, чтобы с помощью $cond для каждого результата рассчитывать:

{ "$group": { 
    "_id": "$issue", 
    "agree": { "$sum": { "$cond": [ { "$eq": [ "$resp", "agree" ] }, 1, 0 ] } }, 
    "disagree": { "$sum": { "$cond": [ { "$eq": [ "$resp", "disagree" ] }, 1, 0 ] } }, 
    "total": { "$sum": 1 } 
}} 

Так что это просто тест, чтобы увидеть, что текущее значение «соответственно» в документе, и только приращении счет, когда он соответствует.

Обратите внимание, что вы можете обрезать это, сохранив в основном true/false в документе в качестве значения.

+0

Работает отлично. И достаточно сложно, что я не чувствую себя плохо, не понимая этого. Красиво сыграл! –