2014-01-24 7 views
2

Мне нужно собрать свою коллекцию на основе определенного интервала времени.Как я могу агрегировать документы по временному интервалу в MongoDB?

Как вы думаете, мне не нужно рассчитывать, например. в час наш день.

Мне нужно агрегировать в соответствии с интервалом в 30 минут (или любым другим). Допустим, первый документ был создан в 15:45. Затем есть еще 5 документов, созданных между 15:45 и 16:15. Итак, в этот промежуток времени у меня есть 6 документов. Таким образом, первым документом результата MapReduce является документ со счетом 6.

Скажем, следующий документ создан 4:35 вечера и еще 3 в 16:40.

Так что следующий документ результата MapReduce представляет собой документ с подсчетом 4.

И так далее ...

В настоящее время моей функция карты выглядит следующим образом:

var map = function() {          
     var key = {name: this.name, minute: this.timestamp.getMinutes()}; 
     emit(key, {count: 1}) 
}; 

Так что ничего особенного. В настоящее время я группирую каждую минуту, чего я не хочу в конце. Здесь, вместо минуты, мне нужно иметь возможность проверить интервал времени, описанный выше.

И моя функция уменьшения:

var reduce = function(key, values) 
{ 
    var sum = 0; 
    values.forEach(function(value) 
    { 
     sum += value['count']; 
    }); 
    return {count: sum}; 
}; 

Выход это так:

{ 
0: "{ "_id" : { "name" : "A" , "minute" : 11.0} , "value" : { "count" : 1.0}}", 
1: "{ "_id" : { "name" : "B" , "minute" : 41.0} , "value" : { "count" : 6.0}}", 
2: "{ "_id" : { "name" : "B" , "minute" : 42.0} , "value" : { "count" : 3.0}}", 
3: "{ "_id" : { "name" : "C" , "minute" : 41.0} , "value" : { "count" : 2.0}}", 
4: "{ "_id" : { "name" : "C" , "minute" : 42.0} , "value" : { "count" : 2.0}}", 
5: "{ "_id" : { "name" : "D" , "minute" : 11.0} , "value" : { "count" : 1.0}}", 
6: "{ "_id" : { "name" : "E" , "minute" : 16.0} , "value" : { "count" : 1.0}}" 
} 

Так он рассчитывает/агрегирует документов в минуту, но не мой интервал пользовательского времени.

Любые идеи об этом?

ответ

1

Редактировать: Мой пример с использованием карты уменьшения не работал, но я думаю, что это примерно то, что вы хотите сделать. Я использую проект для определения переменной time, чтобы содержать минуты от вашей временной метки, округленной до 5-минутных интервалов. Это было бы легко с целым делением, но я не думаю, что язык запросов mongodb поддерживает это в настоящее время, поэтому вместо этого вычитаю minutes mod 5 из минут, чтобы получить число, которое меняется каждые 5 минут. Тогда группа по имени и этому счетчику времени должна сделать трюк.

query = [ 
    { 
     "$project": { 
      "_id":"$_id", 
      "name":"$name", 
      "time": { 
       "$subtract": [ 
        {"$minute":"$timestamp"}, 
        {"$mod": [{"$minute":"$timestamp"}, 5]} 
       ] 
      } 
     } 
    }, 
    { 
     "$group": {"_id": {"name": "$name", "time": "$time"}, "count":{"$sum":1}} 
    } 
] 
db.foo.aggregate(query) 
+0

Спасибо, но это не сработает. Допустим, мы используем вас с 30 (Math.floor (timestamp.getMinutes()/30), это означает, что мы можем группировать только полчаса. Таким образом, документ в 14:25 и 14:35 будет засчитан дважды – user3169506

+0

I отредактировал мой комментарий.Я думаю, что это должно сработать. Документ 14:25 попадет в 25 div 30 = 0, 14:35-минутный документ в 35 div 30 = 1 минута. Для ясности вы можете использовать '30 * Math.floor (timestamp.getMinutes()/30) '. Конечно, в зависимости от вашего набора данных, вероятно, имеет смысл добавить фактор на час, день, месяц, год, иначе 14:35 и 15:35 закончится в той же скобке – Mzzl

+1

Вы хотите объединить на 30-минутный период с произвольной начальной точки, а не с часа? Итак, период от 14:35 до 15:05? – Mzzl

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