2013-05-30 5 views
2

Я пытаюсь объединить общую сумму пакетов в этом документе.Mongodb Возможно ли агрегировать объект?

{ 
    "_id" : ObjectId("51a6cd102769c63e65061bda"), 
    "capture" : "1369885967", 
    "packets" : { 
     "0" : "595", 
     "1" : "596", 
     "2" : "595", 
     "3" : "595", 
     ... 
    } 
} 

Ближайший я могу получить около

db.collection.aggregate({ $match: { capture : "1369885967" } }, {$group: { _id:null, sum: {$sum:"$packets"}}}); 

Однако она возвращает сумму 0, что, очевидно, не так.

{ "result" : [ { "_id" : null, "sum" : 0 } ], "ok" : 1 } 

Как я могу получить сумму всех пакетов?

+0

Вам нужно '$ отстегнуть' этот подкомплекс 'packets', также вы можете изменить этот подзадач в массив – Sammaye

+0

, который невозможно для объекта? когда было бы целесообразно использовать объект вместо этого, если это так? – resting

+0

А вы знаете, что у вас есть объект .... хм .... нет – Sammaye

ответ

3

Поскольку у вас есть значения в объект вместо массива, вы должны будете использовать MapReduce.

// Emit the values as integers 

var mapFunction = 
    function() { 
    for (key in this.packets) { 
     emit(null, parseInt(this.packets[key])); 
    } 
    } 

// Reduce to a simple sum 

var reduceFunction = 
    function(key, values) { 
    return Array.sum(values); 
    } 

> db.collection.mapReduce(mapFunction, reduceFunction, {out: {inline:1}}) 
{ 
    "results" : [ 
     { 
      "_id" : null, 
      "value" : 2381 
     } 
    ], 
    "ok" : 1, 
} 

Если это вообще возможно, вы должны излучать значения как массив числового типа, а не так, что дает вам больше возможностей (т.е. агрегации) и (если набор данных не велик), вероятно, выигрыш в производительности.

+0

Я рассматриваю, должен ли я изменить структуру для хранения пакетов как Массив вместо этого. Я уверен, изменит значение пакетов на числовые. Любые рекомендации в отношении первого, учитывая, что я могу делать различные запросы, например, находить, какое время как самые высокие или самые низкие пакеты? В основном различные отношения между временем и пакетами. – resting

1

Если вы не знаете, сколько ключей находится в пакетном поддокументе, и поскольку вы также, кажется, сохраняете counts как строки (почему ???), вам придется использовать mapReduce.

Что-то вроде:

m=function() { 
    for (f in "this.packets") { 
     emit(null, +this.packets[f]); 
}; 
r=function(k, vals) { 
    int sum=0; 
    vals.forEach(function(v) { sum+=v; }); 
    return sum; 
} 

db.collection.mapreduce(m, r, {out:{inline:1}, query:{your query condition here}}); 
+0

Ну, да, это сработало бы, если бы пакеты были массивом числового типа; '" errmsg ":" exception: $ unwind: значение в конце пути пути должно быть массивом "'. –

+0

Ожидайте, чтобы ваши значения чисел были сохранены в виде строк? –

+0

обновил мой ответ, чтобы обслуживать обе строки вместо цифр и неизвестное количество полей. Извините, неправильно прочитал вопрос раньше. –

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