Aggregation

This extension provides support for the MongoDB aggregation functionality wrapping corresponding commands into PHP methods of yii\mongodb\Command.

Single Purpose Aggregation Operations

The simplest MongoDB aggregation operations are count and distinct, which are available via yii\mongodb\Command::count() and yii\mongodb\Command::distinct() correspondingly. For example:

$booksCount = Yii::$app->mongodb->createCommand()->count('books', ['category' => 'programming']);

You may as well use yii\mongodb\Collection::count() and yii\mongodb\Collection::distinct() shortcut methods:

$booksCount = Yii::$app->mongodb->getCollection('books')->count(['category' => 'programming']);

Methods count() and distinct() are also available at yii\mongodb\Query class:

$booksCount = (new Query())
    ->from('books')
    ->where(['category' => 'programming'])
    ->count();

Pipeline

Aggregation Pipeline can be executed via yii\mongodb\Command::aggregate(). The following example display how you can group books by authorId field:

$authors = Yii::$app->mongodb->createCommand()->aggregate('books', [
    [
        '$group' => [
            '_id' => '$authorId',
        ],
    ],
]);

You may as well use yii\mongodb\Collection::aggregate() as shortcut. In the following example we are grouping books by both authorId and category fields:

$collection = Yii::$app->mongodb->getCollection('books');
$authors = $collection->aggregate([
    [
        '$group'   => [
            '_id'      => '$authorId',
            'category' => '$category',
        ],
    ],
]);

Multiple pipelines can be specified for more sophisticated aggregation. In the following example we are grouping books by authorId field, sorting them by createdAt field descending and then we are limiting the result to 100 documents skipping first 300 records.

$collection = Yii::$app->mongodb->getCollection('books');
$authors = $collection->aggregate([
    [
        '$match' => [
            'name' => ['$ne' => ''],
        ],
    ],
    [
        '$group' => [
            '_id' => '$authorId',
        ],
    ],
    [
        '$sort' => ['createdAt' => -1]
    ],
    [
        '$skip' => 300
    ],
    [
        '$limit' => 100
    ],
]);

Please refer to MongoDB Aggregation Pipeline Docs for detailed information about pipeline specifications.

Aggregation via yii\mongodb\Query

Simple aggregations can be performed via following methods of the yii\mongodb\Query class:

  • sum() - returns the sum of the specified column values.
  • average() - returns the average of the specified column values.
  • min() - returns the minimum of the specified column values.
  • max() - returns the maximum of the specified column values.

In case of these methods invocation yii\mongodb\Query::$where will be used for $match pipeline composition.

use yii\mongodb\Query;

$maxPrice = (new Query())
    ->from('books')
    ->where(['name' => ['$ne' => '']])
    ->max('price', $db);

Map Reduce

Map Reduce can be executed via yii\mongodb\Command::mapReduce().

$result = Yii::$app->mongodb->createCommand()->mapReduce('books',
    'function () {emit(this.status, this.amount)}',
    'function (key, values) {return Array.sum(values)}',
    'mapReduceOut',
    ['status' => ['$lt' => 3]]
);

You may as well use yii\mongodb\Collection::mapReduce() as shortcut.

$result = Yii::$app->mongodb->getCollection('books')->mapReduce(
    'function () {emit(this.status, this.amount)}',
    'function (key, values) {return Array.sum(values)}',
    'mapReduceOut',
    ['status' => ['$lt' => 3]]
);