2015-01-20 2 views
1

У меня есть набор данных о событиях, которые я бы хотел выполнить для агрегирования/группировки, чтобы суммировать данные событий в один результат. У меня возникла проблема с тем, что моя голова обернулась вокруг того, как организовать данные так, как я хочу вернуть результат.Группа MongoDB на нескольких уровнях

выборка данных:

db.events.find ({})

{ 
    eventId : "abc", 
    eventDate : 1420088400000, 
    eventLength : 1800000, 
    eventStart : 59100000, 
    attendees : [ 
     "userA", 
     "userB", 
     "userC" 
    ], 
    otherData : "...", 
    etc : "..." 
},{ 
    eventId : "def", 
    eventDate : 1421557200000, 
    eventLength : 3600000, 
    eventStart : 36000000, 
    attendees : [ 
     "userA", 
     "userG", 
     "userZ" 
    ], 
    otherData : "...", 
    etc : "..." 
},{ 
    eventId : "ghi", 
    eventDate : 1420088400000, 
    eventLength : 7200000, 
    eventStart : 45000000, 
    attendees : [ 
     "userD", 
     "userE", 
     "userA" 
    ], 
    otherData : "...", 
    etc : "..." 
} 

В основном/и длина дата/время, в в все хранятся до тех пор, или INT, представляющая миллисекунды, так что добавление EVENTDATE + eventStart даст вам дату и время начала в UTC. Добавление eventDate + eventStart + eventLength даст вам время окончания события в UTC.

Что я пытаюсь сделать, это создать и заполнить совокупность, которая позволяет мне сопоставлять $ на userId у участников (здесь нет проблем), но отображает группировку данных по дням/неделям/месяцам/годам/в целом.

Так образец результат был бы, например, (и это не с точностью до времени в данной выборке выше, но смотря для того, как сценарий этой группировки ..)

{ 
    userId : "userA", 
    req : 75.0, 
    totals : [ 
     { 
      period : "day", 
      events : 2,    //this means two event for today 
      eventsLength : 7200000, //$sum of the 2 events length 
     },{ 
      period : "week", 
      events : 3,    //this means 3 events in the week 
      eventsLength : 9600000, //$sum of the 3 events length 
     },{ 
      period : "month", 
      events : 8,    //this means 8 events in the month 
      eventsLength : 15000000, //$sum of the 8 events length 
     },{ 
      period : "year", 
      events : 15,    //this means 15 events in the year 
      eventsLength : 15000000, //$sum of the 15 events length 
     },{ 
      period : "overall", 
      events : 23,    //this means 23 events lifetime 
      eventsLength : 72000000, //$sum of the 23 events length 
     } 
    ] 
} 

Так что для каждого «периода «Я в основном хочу сохранить текущую итоговую сумму и суммировать значение eventLength и количество событий. Значение «req» означает текущую дату, пользователь завершил 3/4 события (75%). Это не зависит от итогов, в основном это всего лишь процент, чтобы сказать, что цель - 4 события в неделю, и вот ваш процент завершен. Таким образом, вы видите в «недельный» период, у них только 3 из 4 в качестве цели.

В моем агрегате я попробовал сочетание $ матча, $ проекта и $ группы, чтобы попытаться сделать этот вывод, но я надеялся, что кто-то может помочь с группировки по нарастающему итогу ..

У меня есть дата/миллисекунды, рассчитанные для каждого периода с текущей датой, поэтому у меня уже есть предопределенные переменные, я просто не знаю, как структурировать агрегат/группировку для получения этого результата.

любая помощь оценивается!

+0

Незначительный nitpick в построении вашего вопроса (конструктивная критика). Структура данных результата, которую вы считаете, недействительна для любого языка, но давайте просто предположим JSON, поэтому недействительны. Возможно, вы имеете в виду массив каждой группы.Подробнее о самом вопросе вы можете сделать это на нескольких глубинах, но это может быть не очень практичным в одном утверждении. Другое неизвестное здесь - «req». Как вы знаете, что 3/4 на основе модели данных? И к какой метрике она применяется? «неделя», «день», «год»? Все это задает более ясный вопрос. Но рассмотрите также заявления. –

+0

Привет, Нил, да, скорее, чем набор периодов, это будет массив. Я надеялся, что с каждым элементом массива я могу запустить группу, событие, если бы у меня было 5 операторов группы, чтобы добавить каждый элемент данных к итоговым значениям массив .. таким образом он будет отображаться как «общая сумма», однако в результирующий набор данных будет добавлено 5 результатов. –

+1

«req» или требование будет основываться на неделе, на которую наступает текущая дата, M -> Солнце (ISO). –

ответ

0

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

{ 
    $match: {userId : "ABC123"} 
},{ 
    $project : { 
    _id : 0, 
    d : {$cond:{if:{$and:[{$gte:["$eventDate", "${dayStart}"]},{$lte:["$eventDate", "${dayEnd}"]}]}, 
     then: {d : "$eventLength", c : {"$literal" : 1}}, 
     else: null } 
    }, 
    w : {$cond:{if:{$and:[{$gte:["$eventDate","${weekStart}"]},{$lte:["$eventDate", "${weekEnd}"]}]}, 
     then: {d : "$eventLength", c : {"$literal" : 1}}, 
     else: null } 
    }, 
    m : {$cond:{if:{$and:[{$gte:["$eventDate","${monthStart}"]},{$lte:["$eventDate","${monthEnd}"]}]}, 
     then: {d : "$eventLength", c : {"$literal" : 1}}, 
     else: null } 
    }, 
    y : {$cond:{if:{$and:[{$gte:["$eventDate","${yearStart}"]},{$lte:["$eventDate","${yearEnd}"]}]}, 
     then: {d : "$eventLength", c : {"$literal" : 1}}, 
     else: null } 
    }, 
    o : {$cond:{if:{$lte:["$eventDate","${yearEnd}"]}, 
     then: {d : "$eventLength", c : {"$literal" : 1}}, 
     else: null } 
    } 
} 
},{ 
$group : { 
    _id : null, 
    day_d : {$sum : "$d.d"}, 
    day_c : {$sum : "$d.c"}, 
    week_d : {$sum : "$w.d"}, 
    week_c : {$sum : "$w.c"}, 
    month_d : {$sum : "$m.d"}, 
    month_c : {$sum : "$m.c"}, 
    year_d : {$sum : "$y.d"}, 
    year_c : {$sum : "$y.c"}, 
    over_d : {$sum : "$o.d"}, 
    over_c : {$sum : "$o.c"} 
} 
},{ 
$project : { 
    _id : 0, 
    day : {events : "$day_c", millisTotal : "$day_d"}, 
    week : {events : "$week_c", millisTotal : "$week_d"}, 
    month : {events : "$month_c", millisTotal : "$month_d"}, 
    year : {events : "$year_c", millisTotal : "$year_d"}, 
    overall : {events : "$over_c", millisTotal : "$over_d"}, 
    req : { 
     $cond : { 
      if : { $gte : ["$week_c", 4]}, then : 100, 
      else : { 
       $cond : { 
        if : { $eq : ["$week_c", 3] }, then : 75, 
        else : { 
         $cond : { 
          if : { $eq : ["$week_c", 2] }, then : 50, 
          else : { 
           $cond : { 
            if : { $eq : ["$week_c", 1] }, then : 25, 
            else : 0 
           } 
          } 
         } 
        } 
       } 
      } 
     } 
    } 
} 
} 

Это формирует выходной сигнал, который выглядит следующим образом ..

{ 
day : { 
    events : 1, 
    millisTotal : 7200000 
}, 
week : { 
    events : 2, 
    millisTotal : 14400000 
}, 
month : { 
    events : 17, 
    millisTotal : 87345000 
}, 
year : { 
    events : 17, 
    millisTotal : 87345000 
}, 
overall : { 
    events : 18, 
    millisTotal : 92745000 
}, 
req : 50 
} 

Одна вещь, которую я заметил, это почти невозможно, чтобы $ проект обратно в элемент массива, так что я мог бы иметь «totalals: []» с каждой коллекцией периодов как элемент массива, однако это работает на данный момент. Если у кого есть обратная связь или лучший способ выполнить это, я буду оставьте это немного открытым и посмотрите, появятся ли какие-либо более качественные ответы. Причина, по которой мне хотелось бы, чтобы это как массив итогов, - это логика, которая использует этот вывод, может быть более динамичной и не ожидать определенного набора «ключей» «как день/неделя/месяц/год/в целом.

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