/** * Perform an aggregation using the aggregation framework * * @link http://www.php.net/manual/en/mongocollection.aggregate.php * @param array $pipeline * @param array $op * @return array */ public function aggregate(array $pipeline, array $op = []) { if (!TypeConverter::isNumericArray($pipeline)) { $operators = func_get_args(); $pipeline = []; $options = []; $i = 0; foreach ($operators as $operator) { $i++; if (!is_array($operator)) { trigger_error("Argument {$i} is not an array", E_WARNING); return; } $pipeline[] = $operator; } } else { $options = $op; } if (isset($options['cursor'])) { $options['useCursor'] = true; if (isset($options['cursor']['batchSize'])) { $options['batchSize'] = $options['cursor']['batchSize']; } unset($options['cursor']); } else { $options['useCursor'] = false; } try { $cursor = $this->collection->aggregate(TypeConverter::fromLegacy($pipeline), $options); return ['ok' => 1.0, 'result' => TypeConverter::toLegacy($cursor), 'waitedMS' => 0]; } catch (\MongoDB\Driver\Exception\Exception $e) { throw ExceptionConverter::toLegacy($e, 'MongoResultException'); } }
/** * {@inheritdoc} */ public function aggregate(array $pipeline, array $options = []) { $event = $this->startQueryLogging(__FUNCTION__, null, $pipeline, $options); $result = parent::aggregate($pipeline, $options); $this->logger->logQuery($event); return $result; }
public function aggregate(array $pipeline, array $options = [], $fillModels = true) { return $this->getQueryResult(parent::aggregate($pipeline, $options), $fillModels); }
/** * Execute the query as a fresh "select" statement. * * @param array $columns * @return array|static[] */ public function getFresh($columns = []) { // If no columns have been specified for the select statement, we will set them // here to either the passed columns, or the standard default of retrieving // all of the columns on the table using the "wildcard" column character. if (is_null($this->columns)) { $this->columns = $columns; } // Drop all columns if * is present, MongoDB does not work this way. if (in_array('*', $this->columns)) { $this->columns = []; } // Compile wheres $wheres = $this->compileWheres(); // Use MongoDB's aggregation framework when using grouping or aggregation functions. if ($this->groups or $this->aggregate or $this->paginating) { $group = []; // Add grouping columns to the $group part of the aggregation pipeline. if ($this->groups) { foreach ($this->groups as $column) { $group['_id'][$column] = '$' . $column; // When grouping, also add the $last operator to each grouped field, // this mimics MySQL's behaviour a bit. $group[$column] = ['$last' => '$' . $column]; } // Do the same for other columns that are selected. foreach ($this->columns as $column) { $key = str_replace('.', '_', $column); $group[$key] = ['$last' => '$' . $column]; } } // Add aggregation functions to the $group part of the aggregation pipeline, // these may override previous aggregations. if ($this->aggregate) { $function = $this->aggregate['function']; foreach ($this->aggregate['columns'] as $column) { // Translate count into sum. if ($function == 'count') { $group['aggregate'] = ['$sum' => 1]; } else { $group['aggregate'] = ['$' . $function => '$' . $column]; } } } // When using pagination, we limit the number of returned columns // by adding a projection. if ($this->paginating) { foreach ($this->columns as $column) { $this->projections[$column] = 1; } } // The _id field is mandatory when using grouping. if ($group and empty($group['_id'])) { $group['_id'] = null; } // Build the aggregation pipeline. $pipeline = []; if ($wheres) { $pipeline[] = ['$match' => $wheres]; } if ($group) { $pipeline[] = ['$group' => $group]; } // Apply order and limit if ($this->orders) { $pipeline[] = ['$sort' => $this->orders]; } if ($this->offset) { $pipeline[] = ['$skip' => $this->offset]; } if ($this->limit) { $pipeline[] = ['$limit' => $this->limit]; } if ($this->projections) { $pipeline[] = ['$project' => $this->projections]; } // Execute aggregation return $this->collection->aggregate($pipeline)->toArray(); } elseif ($this->distinct) { // Return distinct results directly $column = isset($this->columns[0]) ? $this->columns[0] : '_id'; // Execute distinct if ($wheres) { $result = $this->collection->distinct($column, $wheres); } else { $result = $this->collection->distinct($column); } return $result; } else { $columns = []; // Convert select columns to simple projections. foreach ($this->columns as $column) { $columns[$column] = true; } // Add custom projections. if ($this->projections) { $columns = array_merge($columns, $this->projections); } $options = []; if ($columns) { $options = ['projection' => $columns]; } // Apply order, offset, limit and hint if ($this->orders) { $options['sort'] = $this->orders; } if ($this->offset) { $options['skip'] = $this->offset; } if ($this->limit) { $options['limit'] = $this->limit; } // Execute query and get $cursor = $this->collection->find($wheres, $options); // Return results as an array with numeric keys return iterator_to_array($cursor, false); } }