2

У меня есть кластер mongo sharded, где я сохраняю данные из системы мониторинга виртуальных машин (zabbix ecc). Теперь я хочу получить некоторую информацию из db, например avg memfree за последние 2 дня одного vm. Я прочитал учебники об агрегировании, а также сравнение с sql, но я не понимаю, как запрашивать документы временных рядов (написанные как манго на веб-семинарах).Как агрегировать документы временных рядов в mongodb

Пример: У меня есть коллекция со многими из этих докторов (один документ представляет собой 1 час):

"_id" : ObjectId("5558ab960e8956234285de14"), 
    "timestamp_hour" : ISODate("2014-10-13T23:00:00.000+02:00"), 
    "name" : "memfree", 
    "unity" : "B", 
    "values" : { 
     "0" : { 
      "0" : 2041004032.0000000000000000, 
      "1" : 2041004032.0000000000000000, 
      "2" : 2041004032.0000000000000000, 
      "3" : 2041004032.0000000000000000, 
      "4" : 2041004032.0000000000000000, 
      "5" : 2041004032.0000000000000000, 
      "6" : 2041004032.0000000000000000, 
      "7" : 2041004032.0000000000000000, 
      "8" : 2041004032.0000000000000000, 
      "9" : 2041004032.0000000000000000, 
      "10" : 2041004032.0000000000000000, 
      "11" : 2041004032.0000000000000000, 
      "12" : 2041004032.0000000000000000, 
      "13" : 2041004032.0000000000000000, 
      "14" : 2041004032.0000000000000000, 
      "15" : 2041004032.0000000000000000, 
      "16" : 2041004032.0000000000000000, 
      "17" : 2041004032.0000000000000000, 
      "18" : 2041004032.0000000000000000, 
      "19" : 2041004032.0000000000000000, 
      "20" : 2041004032.0000000000000000, 
      "21" : 2041004032.0000000000000000, 
      "22" : 2041004032.0000000000000000, 
      "23" : 2041004032.0000000000000000, 
      "24" : 2041004032.0000000000000000, 
      "25" : 2041004032.0000000000000000, 
      "26" : 2041004032.0000000000000000, 
      "27" : 2041004032.0000000000000000, 
      "28" : 2041004032.0000000000000000, 
      "29" : 2041004032.0000000000000000, 
      "30" : 2041004032.0000000000000000, 
      "31" : 2041004032.0000000000000000, 
      "32" : 2041004032.0000000000000000, 
      "33" : 2041004032.0000000000000000, 
      "34" : 2041004032.0000000000000000, 
      "35" : 2041004032.0000000000000000, 
      "36" : 2041004032.0000000000000000, 
      "37" : 2041004032.0000000000000000, 
      "38" : 2041004032.0000000000000000, 
      "39" : 2041004032.0000000000000000, 
      "40" : 2041004032.0000000000000000, 
      "41" : 2041004032.0000000000000000, 
      "42" : 2041004032.0000000000000000, 
      "43" : 2041004032.0000000000000000, 
      "44" : 2041004032.0000000000000000, 
      "45" : 2041004032.0000000000000000, 
      "46" : 2041004032.0000000000000000, 
      "47" : 2041004032.0000000000000000, 
      "48" : 2041004032.0000000000000000, 
      "49" : 2041004032.0000000000000000, 
      "50" : 2041004032.0000000000000000, 
      "51" : 2041004032.0000000000000000, 
      "52" : 2041004032.0000000000000000, 
      "53" : 2041004032.0000000000000000, 
      "54" : 2041004032.0000000000000000, 
      "55" : 2041004032.0000000000000000, 
      "56" : 2041004032.0000000000000000, 
      "57" : 2041004032.0000000000000000, 
      "58" : 2041004032.0000000000000000, 
      "59" : 2041004032.0000000000000000 
     }, 
     "1" : { 
      "0" : 2041004032.0000000000000000, 
      "1" : 2041004032.0000000000000000, 
      "2" : 2041004032.0000000000000000, 
      "3" : 2041004032.0000000000000000, 
      "4" : 2041004032.0000000000000000, 
      "5" : 2041004032.0000000000000000, 
      "6" : 2041004032.0000000000000000, 
      "7" : 2041004032.0000000000000000, 
      "8" : 2041004032.0000000000000000, 
      "9" : 2041004032.0000000000000000, 
      "10" : 2041004032.0000000000000000, 
      "11" : 2041004032.0000000000000000, 
      "12" : 2041004032.0000000000000000, 
      "13" : 2041004032.0000000000000000, 
      "14" : 2041004032.0000000000000000, 
      "15" : 2041004032.0000000000000000, 
      "16" : 2041004032.0000000000000000, 
      "17" : 2041004032.0000000000000000, 
      "18" : 2041004032.0000000000000000, 
      "19" : 2041004032.0000000000000000, 
      "20" : 2041004032.0000000000000000, 
      "21" : 2041004032.0000000000000000, 
      "22" : 2041004032.0000000000000000, 
      "23" : 2041004032.0000000000000000, 
      "24" : 2041004032.0000000000000000, 
      "25" : 2041004032.0000000000000000, 
      "26" : 2041004032.0000000000000000, 
      "27" : 2041004032.0000000000000000, 
      "28" : 2041004032.0000000000000000, 
      "29" : 2041004032.0000000000000000, 
      "30" : 2041004032.0000000000000000, 
      "31" : 2041004032.0000000000000000, 
      "32" : 2041004032.0000000000000000, 
      "33" : 2041004032.0000000000000000, 
      "34" : 2041004032.0000000000000000, 
      "35" : 2041004032.0000000000000000, 
      "36" : 2041004032.0000000000000000, 
      "37" : 2041004032.0000000000000000, 
      "38" : 2041004032.0000000000000000, 
      "39" : 2041004032.0000000000000000, 
      "40" : 2041004032.0000000000000000, 
      "41" : 2041004032.0000000000000000, 
      "42" : 2041004032.0000000000000000, 
      "43" : 2041004032.0000000000000000, 
      "44" : 2041004032.0000000000000000, 
      "45" : 2041004032.0000000000000000, 
      "46" : 2041004032.0000000000000000, 
      "47" : 2041004032.0000000000000000, 
      "48" : 2041004032.0000000000000000, 
      "49" : 2041004032.0000000000000000, 
      "50" : 2041004032.0000000000000000, 
      "51" : 2041004032.0000000000000000, 
      "52" : 2041004032.0000000000000000, 
      "53" : 2041004032.0000000000000000, 
      "54" : 2041004032.0000000000000000, 
      "55" : 2041004032.0000000000000000, 
      "56" : 2041004032.0000000000000000, 
      "57" : 2041004032.0000000000000000, 
      "58" : 2041004032.0000000000000000, 
      "59" : 2041004032.0000000000000000 
.... 

я хочу знать средний memfree от «2014-10-13T23: 00: 00.000» в '2014-10-15T23: 00: 00,000. поэтому мне нужно суммировать все значения от 13 до 15 (3600 * 24 * 2 значения). Я думаю, что запрос будет что-то вроде этого, но я не знаю, как объяснить команду Avg .....

db.metrics.aggregate([ 
    { $match: { name: 'memfree' ,timestamp_hour:{$gte: ISODate("2014-10-13T23:00:00.000+02:00")},timestamp_hour:{$lte: ISODate("2014-10-15T23:00:00.000+02:00")} } }, 
    { 
    $group: { 
     _id: "$name", 
     avg: { $avg: "how can get all the values??" } 
    } 
    } 
]) 

любые советы?

благодаря

EDIT: правильный ответ (работает от одного до многих показателей) является:

map = function() { 
    for (var min in this.values) 
    for (sec in this.values[min]){ 
     data = {value: {}, count: {}} 
     data.value[this.name] = this.values[min][sec] 
     data.count[this.name] = 1 
     emit(this.name, data); 
    } 
} 

reduce = function(key, values) { 
    var sum = values.reduce(function(a, b) { 
    out = {value: {}, count: {},avg:0} 
    for (k in b.value){ 
     incount = a.count[k] || 0 
     invalue = a.value[k] || 0 
     out.value[k] = b.value[k]+invalue 
     out.count[k] = b.count[k]+incount 
    } 
    out.avg = out.value[k]/out.count[k] 
    return out 
    }); 
    return sum; 
} 


printjson(db.node0208_26608.mapReduce(map, reduce, 
       { 
       query: { name: {$in:['ioutil','memtotal','memfree']} , 
          timestamp_hour:{$gte: ISODate("2014-09-22T00:00:00.000+02:00")}, 
          timestamp_hour:{$lte: ISODate("2014-09-28T23:00:00.000+02:00")} 
         }, 
       //to write directly on a collection 
       //out:{merge: "map_reduce_out"}, 
      out: {inline:1}, 
      verbose:true 
       }) 
) 

производит этот результат:

{ 
     "results" : [ 
       { 
         "_id" : "ioutil", 
         "value" : { 
           "value" : { 
             "ioutil" : 2495762.106280909 
           }, 
           "count" : { 
             "ioutil" : 601200 
           }, 
           "avg" : 4.15130090865088 
         } 
       }, 
       { 
         "_id" : "memfree", 
         "value" : { 
           "value" : { 
             "memfree" : 28500447903744 
           }, 
           "count" : { 
             "memfree" : 601200 
           }, 
           "avg" : 47405934.636966065 
         } 
       }, 
       { 
         "_id" : "memtotal", 
         "value" : { 
           "value" : { 
             "memtotal" : 635834327040000 
           }, 
           "count" : { 
             "memtotal" : 594000 
           }, 
           "avg" : 1070428160 
         } 
       } 
     ], 
     "counts" : { 
       "input" : NumberLong(499), 
       "emit" : NumberLong(1796400), 
       "reduce" : NumberLong(11), 
       "output" : NumberLong(3) 
     }, 
     "timeMillis" : 37956, 
     "timing" : { 
       "shardProcessing" : 37948, 
       "postProcessing" : 8 
     }, 
     "shardCounts" : { 
       "192.168.0.19:27017" : { 
         "input" : 165, 
         "emit" : 594000, 
         "reduce" : 4, 
         "output" : 1 
       }, 
       "192.168.0.20:27017" : { 
         "input" : 334, 
         "emit" : 1202400, 
         "reduce" : 7, 
         "output" : 2 
       } 
     }, 
     "postProcessCounts" : { 
       "192.168.0.21:27017" : { 
         "input" : NumberLong(3), 
         "reduce" : NumberLong(0), 
         "output" : NumberLong(3) 
       } 
     }, 
     "ok" : 1 
} 
+0

Возможно, вы захотите рассмотреть этот [** ответ **] (http://stackoverflow.com/a/30304776/). – chridam

ответ

1

Это будет трудно достичь, используя структура агрегации. Но он хорошо работает с MapReduce. Что-то вроде этого (непроверено):

// collect *individual* values 
map = function() { 
    for (var min in this.values) 
    for (sec in this.values[min]) 
     data = {value: {}, count: {}} 
     data.value[this.name] = this.values[min][sec] 
     data.count[this.name] = 1 
     emit(null, data); 
} 

// sum values and count 
reduce = function(key, values) { 
    var sum = values.reduce(function(a, b) { 
    out = {value: {}, count: {}} 
    for (k in b.value) 
     incount = a.count[k] || 0 
     invalue = a.value[k] || 0 
     out.value[k] = b.value[k]+invalue 
     out.count[k] = b.count[k]+incount 

    return out 
    }); 
    return sum; 
} 
+0

ok ... если я хочу avg для 3-х показателей (memfree, cputil, diskfree), я должен повторить ту же процедуру 3 раза с другим запросом или можно поместить операторы OR в запрос и сгруппировать результаты в конце? возможно с emit (this.name, this.values ​​[min] [sec]); ? – SUPERALEX

+0

@SUPERALEX У меня нет времени, чтобы написать подробности, но я отредактировал свой ответ соответственно –

+0

спасибо, что первые решения работают; я слегка исправился. Единственное, что я не понимаю, это то, что если я запустил два решения с одинаковой метрикой, это даст немного другое avg, но только если метрика не имеет целочисленных значений ... Я думаю, что есть какая-то проблема округления, но мне все равно много – SUPERALEX

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