/** * Performs aggregation using Mongo "group" command. * @param mixed $keys fields to group by. If an array or non-code object is passed, * it will be the key used to group results. If instance of [[\MongoCode]] passed, * it will be treated as a function that returns the key to group by. * @param array $initial Initial value of the aggregation counter object. * @param \MongoCode|string $reduce function that takes two arguments (the current * document and the aggregation to this point) and does the aggregation. * Argument will be automatically cast to [[\MongoCode]]. * @param array $options optional parameters to the group command. Valid options include: * - condition - criteria for including a document in the aggregation. * - finalize - function called once per unique key that takes the final output of the reduce function. * @return array the result of the aggregation. * @throws Exception on failure. * @see http://docs.mongodb.org/manual/reference/command/group/ */ public function group($keys, $initial, $reduce, $options = []) { if (array_key_exists('condition', $options)) { $options['condition'] = $this->buildCondition($options['condition']); } $token = $this->composeLogToken('group', [$keys, $initial, $reduce, $options]); Yii::info($token, __METHOD__); try { Yii::beginProfile($token, __METHOD__); $operation = new Group($this->dbName, $this->collectionName, $keys, $initial, $reduce, $options); $readPreference = !empty($options['readPreference']) ? $options['readPreference'] : $this->mongoManager->getReadPreference(); $server = $this->mongoManager->selectServer($readPreference); $result = $operation->execute($server); $this->tryResultError($result); Yii::endProfile($token, __METHOD__); return isset($result->retval) ? MongoHelper::resultToArray($result->retval) : []; } catch (\Exception $e) { Yii::endProfile($token, __METHOD__); throw new Exception($e->getMessage(), (int) $e->getCode(), $e); } }
/** * @param \MongoDB\Driver\Cursor $cursor Mongo cursor instance to fetch data from. * @param boolean $all whether to fetch all rows or only first one. * @param string|callable $indexBy value to index by. * @return array|boolean result. * @see Query::fetchRows() */ protected function fetchRowsInternal($cursor, $all, $indexBy) { if ($all) { $rows = []; foreach ($cursor as $row) { $rows[] = MongoHelper::resultToArray($row); } return $rows; } else { foreach ($cursor as $row) { break; } return isset($row) ? MongoHelper::resultToArray($row) : false; } }