Самый быстрый способ получить гистограмму размеров массивов с помощью фреймворка агрегации MongoDB

Я пытаюсь получить список количества записей с массивами разного размера. Я хочу получить распределение размеров массивов для всех записей, чтобы построить гистограмму следующим образом:

          | *
          | *
documents | *         *
          | *  *      *
          |_*__*__*___*__*___
            2  5  6  23  47

               Array Size

Исходные документы выглядят примерно так:

{hubs : [{stuff:0, id:6}, {stuff:1"}, .... ]}
{hubs : [{stuff:0, id:6}]}`

Пока что используется структура агрегации и некоторая справочная информация здесь I ' я придумал

db.sitedata.aggregate([{ $unwind:'$hubs'}, 
                       { $group : {_id:'$_id', count:{$sum:1}}}, 
                       { $group : {_id:'$count', count:{$sum:1}}},
                       { $sort  : {_id: 1}}])

Кажется, это дает мне желаемые результаты, но не очень быстро. Мне интересно, могу ли я сделать что-то подобное, для чего не потребуются два групповых вызова. Синтаксис здесь неправильный, но я пытаюсь поместить значение счетчика в первое поле _id:

db.sitedata.aggregate([{ $unwind:'$hubs'}, 
                       { $group : {_id:{$count:$hubs}, count:1}},
                       { $sort  : { _id: 1 }}])

person Scott    schedule 18.04.2013    source источник
comment
нет способа сделать это за один проход, потому что вы не можете начать подсчет / группировку результатов, пока не закончите подсчет первой группировки. Какую версию MongoDB вы используете?   -  person Asya Kamsky    schedule 19.04.2013
comment
кстати, сколько времени это займет?   -  person Asya Kamsky    schedule 19.04.2013
comment
Хорошо, я подозревал, что это может быть так (вложение запрещено, только цепочка). Это занимает около 4 секунд, что неплохо, но я надеялся, что меньше секунды. Я могу настроить свои данные вместо того, чтобы настраивать запрос сейчас.   -  person Scott    schedule 19.04.2013
comment
верно, один из подходов к ускорению этого процесса - это предварительное агрегирование сумм путем увеличения счетчика при добавлении новых элементов, хотя могут быть и другие - сколько документов у вас идет в конвейер (и является ли это полным collection или вы сначала делаете что-то вроде $ match?)   -  person Asya Kamsky    schedule 19.04.2013
comment
Я сначала не делаю $ match, потому что это сводка справочных данных. Это всего около 60 000 записей, но это совсем немного конвейерной обработки. Я согласен с тем, что добавление счетчика к записи, вероятно, является лучшим вариантом для ускорения запроса путем удаления одной из групп $ в конвейере.   -  person Scott    schedule 19.04.2013


Ответы (1)


Теперь, когда вышла версия 2.6, среда агрегации поддерживает новый оператор массива $size , что позволит вам $project размер массива без необходимости раскручивать и повторно группировать.

db.sitedata.aggregate([{ $project:{ 'count': { '$size':'$hubs'} } }, 
                       { $group : {_id:'$count', count:{$sum:1} } },
                       { $sort  : { _id: 1 } } ] )
person Asya Kamsky    schedule 26.04.2014