Статьи

Вышла MongoDB 2.6

Вступление

MongoDB быстро развивается. Версия 2.2 представила структуру агрегации как альтернативу модели запросов Map-Reduce . Генерация агрегированных отчетов является регулярным требованием для корпоративных систем, и MongoDB блестяще в этом отношении. Если вы новичок в этом, вы можете проверить это введение структуры агрегации или настройки производительности и руководства по моделированию данных .

Давайте повторно используем модель данных, которую я впервые представил, демонстрируя возможности быстрой вставки MongoDB :

1
2
3
4
5
{
        "_id" : ObjectId("5298a5a03b3f4220588fe57c"),
        "created_on" : ISODate("2012-04-22T01:09:53Z"),
        "value" : 0.1647851116706831
}

MongoDB 2.6 Улучшения агрегации

В версии 2.4, если я запускаю следующий запрос агрегации:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
db.randomData.aggregate( [
{
    $match: {
        "created_on" : {
            $gte : new Date(Date.UTC(2012, 0, 1)),
            $lte : new Date(Date.UTC(2012, 0, 10))
        }
    }
}, 
{
    $group: {
        _id : {
            "minute" : {
                $minute : "$created_on"
            }
        }, 
        "values": {
            $addToSet: "$value"
        }
    }
}]);

Я столкнулся с ограничением результата агрегации 16 МБ:

1
2
3
4
5
{
    "errmsg" : "exception: aggregation result exceeds maximum document size (16MB)",
    "code" : 16389,
    "ok" : 0
}

Документы MongoDB ограничены 16 МБ , а до версии 2.6 результатом агрегации был документ BSON. Версия 2.6 заменила его курсором.

Выполнение того же запроса на 2.6 дает следующий результат:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
db.randomData.aggregate( [
{
    $match: {
        "created_on" : {
            $gte : new Date(Date.UTC(2012, 0, 1)),
            $lte : new Date(Date.UTC(2012, 0, 10))
        }
    }
}, 
{
    $group: {
        _id : {
            "minute" : {
                $minute : "$created_on"
            }
        }, 
        "values": {
            $addToSet: "$value"
        }
    }
}])
.objsLeftInBatch();
14

Я использовал метод objsLeftInBatch на основе курсора для проверки типа результата агрегирования, и ограничение в 16 МБ больше не применяется к общему результату. Внутренние результаты курсора являются обычными документами BSON, следовательно, они по-прежнему ограничены 16 МБ, но это намного более управляемо, чем предыдущий общий предел результатов.

Версия 2.6 также учитывает ограничения памяти агрегации . Полное сканирование коллекции, такое как:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
db.randomData.aggregate( [  
{
    $group: {
        _id : {
            "minute" : {
                $minute : "$created_on"
            }
        }, 
        "values": {
            $addToSet: "$value"
        }
    }
}])
.objsLeftInBatch();

может привести к следующей ошибке:

1
2
3
4
5
{
    "errmsg" : "exception: Exceeded memory limit for $group, but didn't allow external sort. Pass allowDiskUse:true to opt in.",
    "code" : 16945,
    "ok" : 0
}

Итак, теперь мы можем выполнять большие операции сортировки, используя параметр allowDiskUse:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
db.randomData.aggregate( [  
{
    $group: {
        _id : {
            "minute" : {
                $minute : "$created_on"
            }
        }, 
        "values": {
            $addToSet: "$value"
        }
    }
}]
,
{
    allowDiskUse : true
})
.objsLeftInBatch();

Версия 2.6 позволяет нам сохранить результат агрегации в другой коллекции, используя недавно добавленную стадию $ out .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
db.randomData.aggregate( [
{
    $match: {
        "created_on" : {
            $gte : new Date(Date.UTC(2012, 0, 1)),
            $lte : new Date(Date.UTC(2012, 0, 10))
        }
    }
}, 
{
    $group: {
        _id : {
            "minute" : {
                $minute : "$created_on"
            }
        }, 
        "values": {
            $addToSet: "$value"
        }
    }
},
{
    $out : "randomAggregates"
}
]);
db.randomAggregates.count();
60

Добавлены новые операторы, такие как let , map , cond , чтобы назвать несколько.

Следующий пример добавит AM или PM к информации о времени каждой конкретной записи события.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var dataSet = db.randomData.aggregate( [
{
    $match: {
        "created_on" : {
            $gte : new Date(Date.UTC(2012, 0, 1)),
            $lte : new Date(Date.UTC(2012, 0, 2))
        }
    }
}, 
{
    $project: {
        "clock" : {
            $let: {
                vars: {
                    "hour": {
                        $substr: ["$created_on", 11, -1]
                    },             
                    "am_pm": { $cond: { if: { $lt: [ {$hour : "$created_on" }, 12 ] } , then: 'AM',else: 'PM'} }
                },
                in: { $concat: [ "$$hour", " ", "$$am_pm"] }               
            }          
        }  
    }
},
{
    $limit : 10
}
]);
dataSet.forEach(function(document)  {
    printjson(document);
});

В результате чего:

01
02
03
04
05
06
07
08
09
10
"clock" : "16:07:14 PM"
"clock" : "22:14:42 PM"
"clock" : "21:46:12 PM"
"clock" : "03:35:00 AM"
"clock" : "04:14:20 AM"
"clock" : "03:41:39 AM"
"clock" : "17:08:35 PM"
"clock" : "18:44:02 PM"
"clock" : "19:36:07 PM"
"clock" : "07:37:55 AM"

Вывод

Версия MongoDB 2.6 содержит множество других улучшений, таких как массовые операции или пересечение индексов . MongoDB постоянно развивается, предлагая жизнеспособную альтернативу для хранения документов. При таких темпах развития, неудивительно, что она была названа базой данных 2013 года .