2014-10-29 2 views
0

У меня есть код этого агрегационного конвейера ниже, который я хотел бы запускать каждый день в году! По существу, вычисление минимальной, максимальной и средней температуры (поле «TEMP») для каждого дня года. На данный момент я назову этот фрагмент кода 365 раз, передавая дату начала и дату окончания дня.Конвейер агрегации MongoDB с петлей

Очевидно, что это очень неэффективно. Есть ли способ закодировать это в mongo, чтобы он быстрее и возвращал массив из 365 средних значений, 365 минут и 365 максимальных значений или что-то в этом роде. Im использует библиотеку часового пояса для получения даты начала и окончания.

collection.aggregate([ 
    { 
    $match:{$and:[ 
     {"UID" : uid}, 
     {"TEMP" :{$exists:true}} 
     {"site" : "SITE123"}, 
     {"updatedAt": {$gte : new Date(START_DATE_ARG), $lte : new Date(END_DATE_ARG)} } 
     ]} 
    }, 

    { "$group": { 
     "_id": "$UID", 
     "avg": { $avg: $TEMP }, 
     "min": { $min: $TEMP }, 
     "max": { $max: $TEMP } 
     } 
    } 
], function(err, result){ 
       if (err){ 
        cb(1, err); 
       } 
       else{ 
        cb(0, result); 
       } 
      }); 
}); 

наборы данных выглядеть следующим образом

.... 
{UID: "123", TEMP: 11, site: "SITE123", updatedAt: ISODate("2014-09-12T21:55:19.326Z")} 
{UID: "123", TEMP: 10, site: "SITE123", updatedAt: ISODate("2014-09-12T21:55:20.491Z")} 
.... 

Любые идеи? Может быть, мы можем передать все отметки времени всех дней года в конвейере агрегации?

спасибо !!

ответ

0

Зачем запускать это на каждый день, когда вы можете просто сделать дату частью ключа группировки? Это то, что date aggregation operators существует, так что вы можете объединить по времени кадров в весь период сразу без зацикливания:

collection.aggregate([ 
    { "$match":{ 
     "UID": uid, 
     "TEMP":{ "$exists": true } 
     "site" : "SITE123", 
     "updatedAt": { 
      "$gte": new Date(START_DATE_ARG), 
      "$lte": new Date(END_DATE_ARG) 
     }} 
    }}, 

    { "$group": { 
     "_id": { 
      "uid": "$UID", 
      "year": { "$year": "$updatedAt" }, 
      "month": { "$month": "$updatedAt" }, 
      "day": { "$dayOfMonth" } 
     }, 
     "avg": { "$avg": "$TEMP" }, 
     "min": { "$min": "$TEMP" }, 
     "max": { "$max": "$TEMP" } 
    }} 
]) 

Или, возможно, просто конденсационная дату до значения временной метки вместо этого. Маленькая хитрость финиковой математики с датой объектами:

collection.aggregate([ 
    { "$match":{ 
     "UID": uid, 
     "TEMP":{ "$exists": true } 
     "site" : "SITE123", 
     "updatedAt": { 
      "$gte": new Date(START_DATE_ARG), 
      "$lte": new Date(END_DATE_ARG) 
     }} 
    }}, 

    { "$group": { 
     "_id": { 
      "uid": "$UID", 
      "date": { 
       "$subtract": [ 
        { "$subtract": [ "$updatedAt", new Date("1970-01-01") ] }, 
        { "$mod": [ 
         { "$subtract": [ "$updatedAt", new Date("1970-01-01") ] }, 
         1000 * 60 * 60 * 24 
        ]} 
       ] 
      } 
     }, 
     "avg": { "$avg": "$TEMP" }, 
     "min": { "$min": "$TEMP" }, 
     "max": { "$max": "$TEMP" } 
    }} 
]) 

Конечно ваш «диапазон дат» здесь теперь все из дат вам требуется, чтобы быть в результатах, так что начало и дата окончания для всех вещи, где вы намеревались зацикливаться. Группировка выполняется в любом случае, чтобы отразить «один день», но, конечно, вы можете изменить это на любой интервал, который вы хотите.

Также обратите внимание, что использование вами $and здесь не требуется. Запросы в MongoDB "и" условия по умолчанию. Единственный раз, когда вам нужен этот оператор для нескольких условий в одном и том же поле, которое в противном случае было бы недействительным JSON/BSON.

+0

Привет, Нейл, спасибо! Что происходит с часовыми поясами? Если я использую встроенные операторы $ dayOfMonth, $ week, есть ли лучшая практика для настройки часового пояса? – opcode

+0

OK Действительно, функция часового пояса пока не реализована. Трек: https://jira.mongodb.org/browse/SERVER-6310 Я думаю, что даже добавление смещения к запросу не сильно поможет из-за летнего сбережения и т. Д. – opcode

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