/**
  * 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');
     }
 }
Exemple #2
0
 /**
  * {@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);
 }
Exemple #4
0
 /**
  * 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);
     }
 }