MongoDB: The ‘cursor’ option is required

При использовании агрегации через устаревший драйвер MongoDB без указания опций возникает ошибка

Throwable; type: [MongoResultException]; code: [9]; message: [localhost:27017: The ‘cursor’ option is required, except for aggregate with the explain argument]; err level: [1 (E_ERROR)]

Внятного описания в документации, что именно должно быть передано в параметре cursor, нет. Так как драйвер ждёт объект, избавиться от ошибки можно, передав в параметрах метода aggregate() в опции cursor пустой объект:

$pipeline = array(array(
    '$group' => array(
        '_id' => null,
        'min' => array('$min' => '$update_time'),
        'max' => array('$max' => '$update_time'),
    ),
));

$options = array('cursor' => new stdClass());

$res = $MongoCollection->aggregate($pipeline, $options);

Пример выше показывает, как выбрать из коллекции минимальную и максимальную запись.

MongoDB: как разделить поле _id после группировки

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

db.my_collection.aggregate([
    {$group: {
        _id: {surname: "$surname", name: "$name"}
    }},
]);

Этот запрос вернёт такой результат:

{_id: {name: "Аттикус", surname: "Финч"}}
{_id: {name: "Индиана", surname: "Джонс"}}
{_id: {name: "Джеймс", surname: "Бонд"}}
{_id: {name: "Рик", surname: "Блейн"}}
{_id: {name: "Уилл", surname: "Кейн"}}

А вложенные документы поднять на уровень выше, нужна проекция:

db.my_collection.aggregate([
    {$group: {
        _id: {surname: "$surname", name: "$name"}
    }},
    {$project: {_id: 0, surname: "$_id.surname", name: "$_id.name"}},
    {$sort: {surname: 1, name: 1}}
]);

Этот запрос вернёт данные в таком виде:

{name: "Рик", surname: "Блейн"}
{name: "Джеймс", surname: "Бонд"}
{name: "Индиана", surname: "Джонс"}
{name: "Уилл", surname: "Кейн"}
{name: "Аттикус", surname: "Финч"}