diff --git a/extensions/mongo/Collection.php b/extensions/mongo/Collection.php index e211d08..5b6c829 100644 --- a/extensions/mongo/Collection.php +++ b/extensions/mongo/Collection.php @@ -426,11 +426,11 @@ class Collection extends Object */ public function aggregate($pipeline, $pipelineOperator = []) { - $token = 'Aggregating from ' . $this->getFullName(); + $args = func_get_args(); + $token = $this->composeLogToken('aggregate', $args); Yii::info($token, __METHOD__); try { Yii::beginProfile($token, __METHOD__); - $args = func_get_args(); $result = call_user_func_array([$this->mongoCollection, 'aggregate'], $args); $this->tryResultError($result); Yii::endProfile($token, __METHOD__); diff --git a/extensions/mongo/Database.php b/extensions/mongo/Database.php index fcc733f..bb919b5 100644 --- a/extensions/mongo/Database.php +++ b/extensions/mongo/Database.php @@ -9,10 +9,13 @@ namespace yii\mongo; use yii\base\Object; use Yii; +use yii\helpers\Json; /** * Database represents the Mongo database information. * + * @property string $name name of this database. This property is read-only. + * * @author Paul Klimov * @since 2.0 */ @@ -32,6 +35,14 @@ class Database extends Object private $_fileCollections = []; /** + * @return string name of this database. + */ + public function getName() + { + return $this->mongoDb->__toString(); + } + + /** * Returns the Mongo collection with the given name. * @param string $name collection name * @param boolean $refresh whether to reload the collection instance even if it is found in the cache. @@ -93,10 +104,21 @@ class Database extends Object * @param string $name name of the collection * @param array $options collection options in format: "name" => "value" * @return \MongoCollection new mongo collection instance. + * @throws Exception on failure. */ public function createCollection($name, $options = []) { - return $this->mongoDb->createCollection($name, $options); + $token = $this->getName() . '.create(' . $name . ', ' . Json::encode($options) . ')'; + Yii::info($token, __METHOD__); + try { + Yii::beginProfile($token, __METHOD__); + $result = $this->mongoDb->createCollection($name, $options); + Yii::endProfile($token, __METHOD__); + return $result; + } catch (\Exception $e) { + Yii::endProfile($token, __METHOD__); + throw new Exception($e->getMessage(), (int)$e->getCode(), $e); + } } /** @@ -104,9 +126,47 @@ class Database extends Object * @param array $command command specification. * @param array $options options in format: "name" => "value" * @return array database response. + * @throws Exception on failure. */ - public function execute($command, $options = []) + public function executeCommand($command, $options = []) { - return $this->mongoDb->command($command, $options); + $token = $this->getName() . '.$cmd(' . Json::encode($command) . ', ' . Json::encode($options) . ')'; + Yii::info($token, __METHOD__); + try { + Yii::beginProfile($token, __METHOD__); + $result = $this->mongoDb->command($command, $options); + $this->tryResultError($result); + Yii::endProfile($token, __METHOD__); + return $result; + } catch (\Exception $e) { + Yii::endProfile($token, __METHOD__); + throw new Exception($e->getMessage(), (int)$e->getCode(), $e); + } + } + + /** + * Checks if command execution result ended with an error. + * @param mixed $result raw command execution result. + * @throws Exception if an error occurred. + */ + protected function tryResultError($result) + { + if (is_array($result)) { + if (!empty($result['errmsg'])) { + $errorMessage = $result['errmsg']; + } elseif (!empty($result['err'])) { + $errorMessage = $result['err']; + } + if (isset($errorMessage)) { + if (array_key_exists('ok', $result)) { + $errorCode = (int)$result['ok']; + } else { + $errorCode = 0; + } + throw new Exception($errorMessage, $errorCode); + } + } elseif (!$result) { + throw new Exception('Unknown error, use "w=1" option to enable error tracking'); + } } } \ No newline at end of file diff --git a/extensions/mongo/Query.php b/extensions/mongo/Query.php index 5f313f4..cce6645 100644 --- a/extensions/mongo/Query.php +++ b/extensions/mongo/Query.php @@ -131,7 +131,7 @@ class Query extends Component implements QueryInterface */ protected function fetchRows($cursor, $all = true, $indexBy = null) { - $token = 'Querying: ' . Json::encode($cursor->info()); + $token = 'find(' . Json::encode($cursor->info()) . ')'; Yii::info($token, __METHOD__); try { Yii::beginProfile($token, __METHOD__); @@ -213,7 +213,7 @@ class Query extends Component implements QueryInterface public function count($q = '*', $db = null) { $cursor = $this->buildCursor($db); - $token = 'Counting: ' . Json::encode($cursor->info()); + $token = 'find.count(' . Json::encode($cursor->info()) . ')'; Yii::info($token, __METHOD__); try { Yii::beginProfile($token, __METHOD__); diff --git a/tests/unit/extensions/mongo/DatabaseTest.php b/tests/unit/extensions/mongo/DatabaseTest.php index e844d9d..6847d2e 100644 --- a/tests/unit/extensions/mongo/DatabaseTest.php +++ b/tests/unit/extensions/mongo/DatabaseTest.php @@ -49,15 +49,22 @@ class DatabaseTest extends MongoTestCase $this->assertFalse($collection === $collectionRefreshed); } - public function testCommand() + public function testExecuteCommand() { $database = $connection = $this->getConnection()->getDatabase(); - $result = $database->execute([ + $result = $database->executeCommand([ 'distinct' => 'customer', 'key' => 'name' ]); $this->assertTrue(array_key_exists('ok', $result)); $this->assertTrue(array_key_exists('values', $result)); } + + public function testCreateCollection() + { + $database = $connection = $this->getConnection()->getDatabase(); + $collection = $database->createCollection('customer'); + $this->assertTrue($collection instanceof \MongoCollection); + } } \ No newline at end of file