public function aggregate($pipeline, array $options = array(), $asCursor = false)
{
// configure through callable
if (is_callable($pipeline)) {
$pipelineConfiguratorCallable = $pipeline;
$pipeline = $this->createAggregator();
call_user_func($pipelineConfiguratorCallable, $pipeline);
}
// get aggregation array
if ($pipeline instanceof Pipeline) {
if ($options && is_array($options)) {
$options = array_merge($pipeline->getOptions(), $options);
} else {
$options = $pipeline->getOptions();
}
$pipeline = $pipeline->toArray();
} else {
if (!is_array($pipeline)) {
throw new Exception('Wrong pipeline specified');
}
}
// log
$client = $this->database->getClient();
if ($client->isDebugEnabled()) {
// record pipeline
if ($client->hasLogger()) {
$client->getLogger()->debug(get_called_class() . ':<br><b>Pipeline</b>:<br>' . json_encode($pipeline));
}
// Check options only in debug mode. In production common exception will raised
if ($options) {
// get db version
$dbVersion = $client->getDbVersion();
// check options for db < 2.6
if (version_compare($dbVersion, '2.6.0', '<')) {
if (!empty($options['explain'])) {
throw new FeatureNotSupportedException('Explain of aggregation implemented only from 2.6.0');
}
if (!empty($options['allowDiskUse'])) {
throw new FeatureNotSupportedException('Option allowDiskUse of aggregation implemented only from 2.6.0');
}
if (!empty($options['cursor'])) {
throw new FeatureNotSupportedException('Option cursor of aggregation implemented only from 2.6.0');
}
}
// check options for db < 3.2
if (version_compare($dbVersion, '3.2.0', '<')) {
if (!empty($options['bypassDocumentValidation'])) {
throw new FeatureNotSupportedException('Option bypassDocumentValidation of aggregation implemented only from 3.2.0');
}
if (!empty($options['readConcern'])) {
throw new FeatureNotSupportedException('Option readConcern of aggregation implemented only from 3.2.0');
}
}
}
}
// return result as cursor
if ($asCursor) {
if (version_compare(\MongoClient::VERSION, '1.5.0', '<')) {
throw new FeatureNotSupportedException('Aggregate cursor supported from driver version 1.5');
}
$cursor = $this->getMongoCollection()->aggregateCursor($pipeline, $options);
return $cursor;
}
// prepare command
$command = array('aggregate' => $this->getName(), 'pipeline' => $pipeline);
// add options
if ($options) {
$command += $options;
}
// aggregate
$status = $this->database->executeCommand($command);
if ($status['ok'] != 1) {
throw new Exception('Aggregate error: ' . $status['errmsg']);
}
// explain response
if (!empty($command['explain'])) {
return $status['stages'];
}
// result response
return $status['result'];
}