2015-08-20 3 views
1

У меня есть следующий наборMongoDB общая сумма встроенных пара ключей объекты

{ 

    "pos": 1 
    "daily": 1, 
    "hourly": { 
    "15": 1, 
    "23": 4 
    } 
} 

ежечасно находится в диапазоне от 0 до 23, я просто хочу, чтобы сгруппировать по позиции и хотите агрегировать ($ суммы) ежедневно и отдельные часы. Почасовое время меня обманывает.

+0

Не уверен, что вы спрашиваете. Вы хотите суммировать все значения в «hourly» или хотите, чтобы каждый «часовой» итог составлял 0..23? –

+0

сумма за отдельные часы @Blakes – Peramanathan

+0

Я думал, вы могли бы это сказать. В любом случае у вас есть обе возможности. –

ответ

0

Вы, вероятно, следует использовать mapReduce для этого, структура агрегации не могут перемещаться ключи объекта:

db.collection.mapReduce(
    function() { 
     var obj = { "daily": this.daily, "hourly": {} }; 
     for (var x=0; x <= 23; x++) { 
      obj.hourly[x] = 0; 
     } 

     var hourly = this.hourly; 
     Object.keys(hourly).forEach(function(hour) { 
      obj.hourly[hour] += hourly[hour]; 
     }); 
     emit(null, obj); 
    }, 
    function(key,values) { 
     var obj = { "daily": 0, "hourly": {} }; 
     for (var x=0; x <= 23; x++) { 
      obj.hourly[x] = 0; 
     } 

     values.forEach(function(value) { 
      obj.daily += value.daily; 
      Object.keys(value.hourly).forEach(function(hour) { 
       obj.hourly[hour] += value.hourly[hour]; 
      }); 
     }); 
     return obj; 
    }, 
    { "out": { "inline": 1 } } 
) 

Или, если вы имеете в виду вы просто хотите общее количество «ежечасно», то сделать это:

db.collection.mapReduce(
    function() { 
     var obj = { "daily": this.daily, "hourly": 0 }; 

     var hourly = this.hourly; 
     hourly.forEach(function(hour) { 
      obj.hourly+= hourly[hour]; 
     }); 
     emit(null, obj); 
    }, 
    function(key,values) { 
     var obj = { "daily": 0, "hourly": 0 }; 
     values.forEach(function(value) { 
      obj.daily += value.daily; 
      obj.hourly += value.hourly; 
     }); 
     return obj; 
    }, 
    { "out": { "inline": 1 } } 
) 

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

db.collection.aggregate([ 
    { "$group": { 
     "_id": null, 
     "daily": { "$sum": "$daily" }, 
     "0": { "$sum": "$hourly.0" }, 
     "1": { "$sum": "$hourly.1" }, 
     "2": { "$sum": "$hourly.2" }, 
     "3": { "$sum": "$hourly.3" }, 
     "4": { "$sum": "$hourly.4" }, 
     "5": { "$sum": "$hourly.5" }, 
     "6": { "$sum": "$hourly.6" } 
    }}, 
    { "$project": { 
     "daily": 1, 
     "hourly": { 
      "0": "$0", 
      "1": "$1", 
      "2": "$2", 
      "3": "$3", 
      "4": "$4", 
      "5": "$5", 
      "6": "$6" 
     } 
    }} 
]) 

Или снова только в общей сложности составляют «ежечасно» значения,

db.collection.aggregate([ 
    { "$group": { 
     "_id": null, 
     "daily": { "$sum": "$daily" }, 
     "hourly": { 
      "$sum": { "$add": [ 
       "$hourly.0",, 
       "$hourly.1", 
       "$hourly.2", 
       "$hourly.3", 
       "$hourly.4", 
       "$hourly.5", 
       "$hourly.6" 
      ]} 
     } 
    }} 
]) 

Вы можете использования конечно код для генерации агрегацию так как они все равно являются структурами данных. Таким образом, для генерации можно использовать аналогичный подход, как показано в примере mapReduce (looping 0..23).

+0

Большое спасибо приятелю. Btw, 'emit (null, obj);' эта строка должна быть 'emit (pos, obj)', поскольку я хочу группировать по позиции – Peramanathan

+0

@Peramanathan. Пример, который я даю в этом случае, создает каждую позицию, суммированную в единственном результате в отличие от документа на «должность». Это, конечно же, другой подход, если это то, чего вы хотите достичь. –

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