2013-06-20 3 views
2

Я использую MongoDb какое-то время и думаю, что это замечательно. У меня есть следующий объект Activity.MongoDB группировка как по дате, так и по текстовым полям

[ Activity ] 
"_id"  : ObjectId("518a6c18e4b079d18de65b6e"), 
"userUrl" : "http://news.bbc.co.uk", 
"userAddress" : "1.2.3.4", 
"requestTime" : ISODate("2013-05-08T15:15:35.780Z"), 
"status" : "success" 

ПРИМЕЧАНИЕ. В поле состояния имеется около 5 различных значений. «ошибка», «недоступна» и т. д.

Итак, я сейчас на стадии подготовки отчетов высокого уровня о нагрузке, но имеющих проблемы с функцией группировки. Например, если я ввожу следующий тест данные: -

db.activity.insert({"userUrl": "http://news.bbc.co.uk", "userAddress" : "1.2.3.4", "requestTime" : new Date('Jan 01, 2013'), "status": "success"}) 
db.activity.insert({"userUrl": "http://news.bbc.co.uk", "userAddress" : "1.2.3.4", "requestTime" : new Date('Jan 01, 2013'), "status": "success"}) 
db.activity.insert({"userUrl": "http://news.bbc.co.uk", "userAddress" : "1.2.3.4", "requestTime" : new Date('Jan 01, 2013'), "status": "error"}) 
db.activity.insert({"userUrl": "http://news.bbc.co.uk", "userAddress" : "1.2.3.4", "requestTime" : new Date('Jan 01, 2013'), "status": "unavailable"}) 
db.activity.insert({"userUrl": "http://news.bbc.co.uk", "userAddress" : "1.2.3.4", "requestTime" : new Date('Jan 02, 2013'), "status": "success"}) 
db.activity.insert({"userUrl": "http://news.bbc.co.uk", "userAddress" : "1.2.3.4", "requestTime" : new Date('Jan 02, 2013'), "status": "error"}) 
db.activity.insert({"userUrl": "http://news.bbc.co.uk", "userAddress" : "1.2.3.4", "requestTime" : new Date('Jan 02, 2013'), "status": "error"}) 
db.activity.insert({"userUrl": "http://news.bbc.co.uk", "userAddress" : "1.2.3.4", "requestTime" : new Date('Jan 02, 2013'), "status": "unavailable"}) 
db.activity.insert({"userUrl": "http://news.bbc.co.uk", "userAddress" : "1.2.3.4", "requestTime" : new Date('Jan 02, 2013'), "status": "unavailable"}) 

... и запустить эту функцию ...

db.activity.group(
{ 
    $keyf : function(doc) { 
     return { "date" : doc.requestTime.getDate() + "/" + doc.requestTime.getMonth() + "/" + doc.requestTime.getFullYear()}; 
    }, 
    initial: { count:0 }, 
    reduce: function(obj, prev) { prev.count++; } 
}) 

... я получаю этот результат ...

[ 
    { 
     "date" : "1/0/2013", 
     "count" : 4 
    }, 
    { 
     "date" : "2/0/2013", 
     "count" : 5 
    } 
] 

Которая работает действительно красиво для группировки только на дату. Мой вопрос в том, как я буду группировать дату (по дням) по статусу?. чтобы получить что-то, как это было бы идеально: -

[ 
    { 
     "date" : "1/0/2013", 
     "success" : 2, 
     "error": 1, 
     "unavailable": 1 
    },     
    }, 
    { 
     "date" : "2/0/2013", 
     "success" : 1, 
     "error": 2, 
     "unavailable": 2 
    } 
] 

... или ...

[ 
    { 
     "date" : "1/0/2013", 
     status: [ 
      "success" : 2, 
      "error": 1, 
      "unavailable": 1 
     ] 
    },     
    }, 
    { 
     "date" : "2/0/2013", 
     status: [ 
      "success" : 1, 
      "error": 2, 
      "unavailable": 2 
     ] 
    } 
] 

ответ

0

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

Здесь идет A/F призывание:

db.activity.aggregate(
    { $group: { 
     _id: { date: '$requestTime' }, 
     success : { 
      $sum: { $cond: [ { $eq: [ 'success', '$status' ] } , 1, 0 ] } 
     }, 
     error : { 
      $sum: { $cond: [ { $eq: [ 'error', '$status' ] } , 1, 0 ] } 
     }, 
     unavailable : { 
      $sum: { $cond: [ { $eq: [ 'unavailable', '$status' ] } , 1, 0 ] } 
     } 
    } } 
); 

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

{ 
    "result" : [ 
     { 
      "_id" : { 
       "date" : ISODate("2013-01-02T00:00:00Z") 
      }, 
      "success" : 1, 
      "error" : 2, 
      "unavailable" : 2 
     }, 
     { 
      "_id" : { 
       "date" : ISODate("2013-01-01T00:00:00Z") 
      }, 
      "success" : 2, 
      "error" : 1, 
      "unavailable" : 1 
     } 
    ], 
    "ok" : 1 
} 
+0

Отличный ответ !!! Заметьте, что я добавил фигурные скобки в конце $ sum, которые недоступны для работы. '$ sum: {$ cond: [{$ eq: ['unavailable', '$ status']}, 1, 0]}' – bobmarksie

+0

Я исправил опечатку! (Кроме того, обычно, если вы считаете, что ответ отвечает на ваш вопрос, вы принимаете этот ответ). – Derick

+0

Готово. Первый раз, используя stackoverflow - попробую ответить на несколько вопросов сам сейчас ... :-) – bobmarksie

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