2013-08-05 4 views
1

Я хочу создать статистику о том, сколько новых документов хранится каждую минуту.MongoDB подсчитывает количество новых документов в минуту на основе _id

Поскольку поле _id со стандартным идентификатором объекта содержит уже временную метку создания документа, я думаю, что должно быть возможно как-то его использовать.

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

Map-Reduce count number of documents in each minute MongoDB

map = function() { 

var created_at_minute = new Date(this.created_at.getFullYear(), 
           this.created_at.getMonth(), 
           this.created_at.getDate(), 
           this.created_at.getHours(), 
           this.created_at.getMinutes()); 
    emit(created_at_minute, {count: 1}); 
} 

reduce = function(key, values) { 
     var total = 0; 
     for(var i = 0; i < values.length; i++) { total += values[i].count; } 
     return {count: total}; 
} 

Согласно документации Монго DB (http://docs.mongodb.org/manual/reference/object-id/) он должен можно получить временную метку из _id, вызвав ObjectId («507f191e810c19729de860ea»). getTimestamp().

Прямо сейчас я понятия не имею, возможно ли вообще использовать эту getTimestamp() внутри функции карты.

Есть ли у кого-нибудь идея, как это сделать или есть лучший способ?

Мне это нужно, чтобы быть осуществимыми в питона или PHP

+0

Функция карта должна быть написана на JavaScript. Я не уверен, что вы имеете в виду «он должен быть реализован в python или php»? Если '_id' является ObjectId, то в документах' getTimestamp' должен работать нормально. Я не понимаю, почему вы этого не пробовали? – WiredPrairie

+0

Сокращение карты написано в javaskiprt, я знаю, но это должно быть исполняемым через php или python ... Я пытаюсь сейчас сделать что-то, но я довольно новичок, чтобы свернуть карту через mongodb – Dukeatcoding

ответ

3

Вы можете сделать это с M/R действительно. getTimestamp() работает в M/R, как он работает в JavaScript на сервере, не имеет значения, является ли ваш язык клиент PHP или Python:

map = function() { 
    var datetime = this._id.getTimestamp(); 

    var created_at_minute = new Date(datetime.getFullYear(), 
            datetime.getMonth(), 
            datetime.getDate(), 
            datetime.getHours(), 
            datetime.getMinutes()); 
    emit(created_at_minute, {count: 1}); 
} 

reduce = function(key, values) { 
    var total = 0; 
    for(var i = 0; i < values.length; i++) { total += values[i].count; } 
    return {count: total}; 
} 

db.so.mapReduce(map, reduce, { out: 'inline' }); 
db.inline.find(); 

который выводит что-то вроде:

{ "_id" : ISODate("2013-08-05T15:24:00Z"), "value" : { "count" : 9 } } 
{ "_id" : ISODate("2013-08-05T15:26:00Z"), "value" : { "count" : 2 } } 

Однако, Я бы предложил вам не использовать M/R, а вместо этого перейти к структуре агрегации, поскольку он намного быстрее, потому что он может использовать индексы и запускаться одновременно. Прямо сейчас у A/F нет оператора, чтобы получить метку времени из поля ObjectID, хотя вы так и должны : должны хранить время на момент ввода. F.E. с документами, как это:

db.so.drop(); 
db.so.insert({ date: new ISODate("2013-08-05T15:24:15") }); 
db.so.insert({ date: new ISODate("2013-08-05T15:24:19") }); 
db.so.insert({ date: new ISODate("2013-08-05T15:24:25") }); 
db.so.insert({ date: new ISODate("2013-08-05T15:24:32") }); 
db.so.insert({ date: new ISODate("2013-08-05T15:24:45") }); 
db.so.insert({ date: new ISODate("2013-08-05T15:25:15") }); 
db.so.insert({ date: new ISODate("2013-08-05T15:25:15") }); 

db.so.aggregate([ 
    { $group: { 
     _id: { 
      y: { '$year': '$date' }, 
      m: { '$month': '$date' }, 
      d: { '$dayOfMonth': '$date' }, 
      h: { '$hour': '$date' }, 
      i: { '$minute': '$date' }, 
     }, 
     count: { $sum : 1 } 
    } } 
]); 

Какие выходы:

{ 
    "result" : [ 
     { 
      "_id" : { 
       "y" : 2013, 
       "m" : 8, 
       "d" : 5, 
       "h" : 15, 
       "i" : 25 
      }, 
      "count" : 2 
     }, 
     { 
      "_id" : { 
       "y" : 2013, 
       "m" : 8, 
       "d" : 5, 
       "h" : 15, 
       "i" : 24 
      }, 
      "count" : 5 
     } 
    ], 
    "ok" : 1 
} 
+0

thx очень сильно, я думаю, что вы может быть правильным с использованием структуры агрегации, сокращение карты, похоже, сейчас не является убийцей с mongo db. только недостаток я должен хранить время вставки «вручную» ... – Dukeatcoding

+0

возможно, как-то можно извлечь временную метку из _id на рабочем шаге, прежде чем применять структуру агрегации. Так как, где нет даты exsists, не извлекать _id.getTimestamp и обновления документа Применить Aggregation Framwork – Dukeatcoding

+0

вы знаете, как получить дату от поддокумента «metadata.timestamp» я попытался {$ Проект: {метка времени: «$ метаданных .timestamp "}}, – Dukeatcoding

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