PHP 8.0.6 Released!

MongoCollection::group

(PECL mongo >=0.9.2)

MongoCollection::groupВыполняет операцию, аналогичную команде SQL GROUP BY

Описание

public MongoCollection::group ( mixed $keys , array $initial , MongoCode $reduce , array $options = array() ) : array

Список параметров

keys

Поля для группировки. Если передан массив или объект без кода, это будет ключ, используемый для группировки результатов.

1.0.4+: Если keys является экземпляром MongoCode, keys будут обрабатываться как функция, которая возвращает ключ для группировки (смотрите пример "Передача функции keys" ниже).

initial

Начальное значение объекта счётчика агрегации.

reduce

Функция, которая принимает два аргумента (текущий документ и агрегацию на данный момент) и выполняет агрегацию.

options

Необязательные параметры для групповой команды. Допустимые варианты:

  • "condition"

    Критерии включения документа в агрегацию.

  • "finalize"

    Функция вызывается один раз для каждой уникальной клавиши, которая принимает окончательный результат функции reduce.

  • "maxTimeMS"

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

Возвращаемые значения

Возвращает массив, содержащий результат.

Список изменений

Версия Описание
PECL mongo 1.5.0 Добавлена опция "maxTimeMS".
PECL mongo 1.2.11 Выдаёт E_DEPRECATED, когда используется options, как scalar.

Примеры

Пример #1 Пример использования MongoCollection::group()

Группирует документы по категориям и создаёт список имён в этой категории.

<?php

$collection
->insert(array("category" => "fruit""name" => "apple"));
$collection->insert(array("category" => "fruit""name" => "peach"));
$collection->insert(array("category" => "fruit""name" => "banana"));
$collection->insert(array("category" => "veggie""name" => "corn"));
$collection->insert(array("category" => "veggie""name" => "broccoli"));

$keys = array("category" => 1);

$initial = array("items" => array());

$reduce "function (obj, prev) { prev.items.push(obj.name); }";

$g $collection->group($keys$initial$reduce);

echo 
json_encode($g['retval']);

?>

Результатом выполнения данного примера будет что-то подобное:

[{"category":"fruit","items":["apple","peach","banana"]},{"category":"veggie","items":["corn","broccoli"]}]

Пример #2 Пример использования MongoCollection::group()

Этот пример не использует никаких ключей, поэтому каждый документ будет иметь свою собственную группу. Он также использует условие: только те документы, которые соответствуют этому условию, будут обрабатываться функцией группировки.

<?php

$collection
->save(array("a" => 2));
$collection->save(array("b" => 5));
$collection->save(array("a" => 1));

// используем все поля
$keys = array();

// устанавливаем начальные значения
$initial = array("count" => 0);

// функция JavaScript для выполнения
$reduce "function (obj, prev) { prev.count++; }";

// используем только те документы, у которых поле "а" больше 1
$condition = array('condition' => array("a" => array( '$gt' => 1)));

$g $collection->group($keys$initial$reduce$condition);

var_dump($g);

?>

Результатом выполнения данного примера будет что-то подобное:

array(4) {
  ["retval"]=>
  array(1) {
    [0]=>
    array(1) {
      ["count"]=>
      float(1)
    }
  }
  ["count"]=>
  float(1)
  ["keys"]=>
  int(1)
  ["ok"]=>
  float(1)
}

Пример #3 Передача функции keys

Если вы хотите сгруппировать по чему-то отличному от имён полей, вы можете передать функцию в качестве первого параметра MongoCollection::group(), и она будет выполняться для каждого документа. Возвращаемое значение функции будет использоваться в качестве значения группировки.

Этот пример демонстрирует группирование по числовому полю по модулю 4.

<?php

$c
->group(new MongoCode('function(doc) { return {mod : doc.num % 4}; }'),
     array(
"count" => 0),
     new 
MongoCode('function(current, total) { total.count++; }'));

?>
add a note add a note

User Contributed Notes 4 notes

up
2
nick at pitchinteractive dot com
9 years ago
Here's my code to do an equivalent of a GROUP BY and a SUM

<?php
$contributionCol
= $db->customers->contribution;
$group = $contributionCol->group(array('date' => true), array('sum' => 0), "function (obj, prev) { prev['sum'] += obj.amount; }");
?>

This groups by the 'date' column and sums over the 'amount' column. In my testing this was much slower than querying all rows and doing the Group by code with PHP. It could just be my particular setup and data set.

Also at first my amount column was a string, which caused the results to be concatenated rather than arithmetic addition, something else to watch out for.

[red.: Instead of this, please use the new aggregation framework. See the documentation for MongoCollection::aggregate]
up
0
ury dot zend at gmail dot com
6 years ago
quoting Evgeniy Abduzhapparov example for correction, since is not working on newest php mongo driver version

instead of use:
<?php
$initial
= array('tags'=>array(), 'count'=>0);
?>
for var tags,
you have to cast the empty array to an object or use new stdClass()
<?php
$initial
= array('tags'=> (object) array(), 'count'=>0);

$initial = array('tags'=> new stdClass(), 'count'=>0);
?>
up
-1
ronan dot guilloux at gmail dot com
8 years ago
Since the $options argument is no longer a scalar (deprecated since the 1.2.11 version of the Mongo's PHP driver), you now must compose your $options as an associative array, otherwise you'll rise a "Implicitly passing condition as $options will be removed in the future" alert.

Example:

<?php

$m
= new Mongo();
$db = $m->selectDB('test');
$collection = new MongoCollection($db, 'FooBar');

// grouping results by categories, where foo is 'bar'
$keys = array('categorie'=>true, 'foo'=>true); // the fields list we want to return
$initial = array('count' => 0); // gets a subtotal for each categorie
$reduce = "function(obj,prev) { prev.count += 1; }"; // yes, this is js code
$conditions = array('foo'=> 'bar');
$grouped = $myColl::group($keys, $initial, $reduce, array('condition'=>$conditions));
$result = $grouped['retval'];

?>
up
-4
Evgeniy Abduzhapparov
10 years ago
Here I am posting how I get tags from my documents. Documents should have 'tags' field which is array of strings:
{'tags':['php', 'mongo']}
<?php
$keys
= array();
$initial = array('tags'=>array(), 'count'=>0);
$reduce = 'function (doc, total) { if (doc.tags.length) {doc.tags.forEach(function (e) {total.tags[e]=total.tags[e]||0; total.tags[e]++; total.count++;});} }';
$criteria = array(
   
'condition' => array(
       
'tags' => array('$exists'=>true)
    ),
);
?>
To Top