2014-09-05 4 views
1

Я использую структуру агрегации MongoDB для агрегирования коллекции записей.MongoDB Совокупные записи с сегодняшнего дня

Соответствующий фрагмент кода:

Record._get_collection().aggregate([ 
     { "$match": { 
      "system_id": system.id 
     }}, 
... 

Как превратить это в совокупности записей для только сегодня?

Record документ имеет utc_timestamp поле, так что я думаю, что это будет что-то вроде:

Record._get_collection().aggregate([ 
     { "$match": { 
      "system_id": system.id, 
      { "$dayOfMonth": "$utc_timestamp" }: 5 
     }}, 
... 

Правильно ли это?

+0

Какой формат поля utc_timestamp? –

ответ

2

Для того, чтобы просто получить записи на текущий день, вам по-прежнему необходимо передать диапазон дат, представляющий начало дня и конец диапазона, который нужно искать. Предполагая, что вы реализовали это в своем классе с DateTimeField тем MongoDB будет использовать BSON date тип, который совместит с операторами агрегирования даты:

Record._get_collection().Aggregate([ 
    { "$match": { 
     "system_id": system.id, 
     "utc_timestamp": { 
      "$gte": datetime.datetime(2014,9,6) 
      "$lt": datetime.datetime(2014,9,7) 
     } 
    }}, 
    { "$group": { 
     "_id": { "$dayOfYear": "$utc_timestamp" } 
     .... 

На том $group уровне эти операторы, как правило, имеет смысл использовать при объединении значений над более широкий диапазон, чем один день или иначе, через час или минуту в течение дня. В противном случае, поскольку даты уже выбраны, все это текущий день, и любой ключ агрегирования для другого поля или значение Null по существу является агрегирующим для этого дня.

Если вместо того, чтобы с помощью «метки времени» вы на самом деле число, представляющее секунды с начала эпохи (тип BSON фактически внутренне использует миллисекунды с начала эпохи), то вы можете построить свой запрос так:

Record._get_collection().Aggregate([ 
    { "$match": { 
     "system_id": system.id, 
     "utc_timestamp": { 
      "$gte": (datetime.datetime(2014,9,6) 
        - datetime.datetime(1970,1,1)).total_seconds() 
      "$lt": (datetime.datetime(2014,9,7) 
        - datetime.datetime(1970,1,1)).total_seconds() 
     } 
    }}, 
    { "$group": { 
     "_id": { 
      "$subtract": [ 
       "$utc_timestamp", 
       { "$mod": [ 
        "$utc_timestamp", 
        60 * 60 * 24 
       ]} 
      ] 
     }, 
     ... 

Или аналогично отрегулируйте для miliseconds, который является более распространенным форматом временной метки эпохи, умножая на 1000. Для группировки стандартной «математики даты» применяется округление совпадающих значений временной метки до текущего дня.

Наконец, MongoEngine поддерживает ComplexDateTimeField, который сохраняет микросекунды, обычно доступные в объектах datetime python. К сожалению, фактическое хранилище в MongoDB является «строкой» в этом случае, поэтому ни математические, ни общие операторы даты действительно недоступны. Но строка в формате YYYY,MM,DD,HH,MM,SS,NNNNNN, который, по крайней мере «лексически» заказал, и поэтому может быть диапазон выбран и расчлененный с $substr, чтобы агрегировать в день, или другой период:

Record._get_collection().Aggregate([ 
    { "$match": { 
     "system_id": system.id, 
     "utc_timestamp": { 
      "$gte": "2014,09,06", "$lt": "2014,09,07" 
     } 
    }}, 
    { "$group": { 
     "_id": { "$substr": [ "$utc_timestamp", 0, 10 ] } 
     ... 

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

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