diff --git a/extensions/mongo/ActiveQuery.php b/extensions/mongo/ActiveQuery.php index 9b7e207..9031723 100644 --- a/extensions/mongo/ActiveQuery.php +++ b/extensions/mongo/ActiveQuery.php @@ -29,10 +29,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface public function all($db = null) { $cursor = $this->buildCursor($db); - $rows = []; - foreach ($cursor as $row) { - $rows[] = $row; - } + $rows = $this->fetchRows($cursor); if (!empty($rows)) { $models = $this->createModels($rows); if (!empty($this->with)) { diff --git a/extensions/mongo/Collection.php b/extensions/mongo/Collection.php index 64242c1..aeae8a9 100644 --- a/extensions/mongo/Collection.php +++ b/extensions/mongo/Collection.php @@ -173,9 +173,12 @@ class Collection extends Object } /** - * @param array $condition - * @param array $fields - * @return \MongoCursor + * Returns a cursor for the search results. + * In order to perform "find" queries use [[Query]] class. + * @param array $condition query condition + * @param array $fields fields to be selected + * @return \MongoCursor cursor for the search results + * @see Query */ public function find($condition = [], $fields = []) { @@ -183,21 +186,6 @@ class Collection extends Object } /** - * @param array $condition - * @param array $fields - * @return array - */ - public function findAll($condition = [], $fields = []) - { - $cursor = $this->find($condition, $fields); - $result = []; - foreach ($cursor as $data) { - $result[] = $data; - } - return $result; - } - - /** * Inserts new data into collection. * @param array|object $data data to be inserted. * @param array $options list of options in format: optionName => optionValue. diff --git a/extensions/mongo/Query.php b/extensions/mongo/Query.php index 16fd8db..1a00b08 100644 --- a/extensions/mongo/Query.php +++ b/extensions/mongo/Query.php @@ -10,6 +10,7 @@ namespace yii\mongo; use yii\base\Component; use yii\db\QueryInterface; use yii\db\QueryTrait; +use yii\helpers\Json; use Yii; /** @@ -104,6 +105,48 @@ class Query extends Component implements QueryInterface } /** + * @param \MongoCursor $cursor Mongo cursor instance to fetch data from. + * @param boolean $all whether to fetch all rows or only first one. + * @param string|callable $indexBy + * @throws Exception + * @return array|boolean + */ + protected function fetchRows(\MongoCursor $cursor, $all = true, $indexBy = null) + { + $token = 'Querying: ' . Json::encode($cursor->info()); + Yii::info($token, __METHOD__); + try { + Yii::beginProfile($token, __METHOD__); + $result = []; + if ($all) { + foreach ($cursor as $row) { + if ($indexBy !== null) { + if (is_string($indexBy)) { + $key = $row[$indexBy]; + } else { + $key = call_user_func($indexBy, $row); + } + $result[$key] = $row; + } else { + $result[] = $row; + } + } + } else { + if ($cursor->hasNext()) { + $result = $cursor->getNext(); + } else { + $result = false; + } + } + Yii::endProfile($token, __METHOD__); + return $result; + } catch (\Exception $e) { + Yii::endProfile($token, __METHOD__); + throw new Exception($e->getMessage(), (int)$e->getCode(), $e); + } + } + + /** * Executes the query and returns all results as an array. * @param Connection $db the Mongo connection used to execute the query. * If this parameter is not given, the `mongo` application component will be used. @@ -112,20 +155,7 @@ class Query extends Component implements QueryInterface public function all($db = null) { $cursor = $this->buildCursor($db); - $result = []; - foreach ($cursor as $row) { - if ($this->indexBy !== null) { - if (is_string($this->indexBy)) { - $key = $row[$this->indexBy]; - } else { - $key = call_user_func($this->indexBy, $row); - } - $result[$key] = $row; - } else { - $result[] = $row; - } - } - return $result; + return $this->fetchRows($cursor, true, $this->indexBy); } /** @@ -138,11 +168,7 @@ class Query extends Component implements QueryInterface public function one($db = null) { $cursor = $this->buildCursor($db); - if ($cursor->hasNext()) { - return $cursor->getNext(); - } else { - return false; - } + return $this->fetchRows($cursor, false); } /** @@ -151,11 +177,22 @@ class Query extends Component implements QueryInterface * @param Connection $db the Mongo connection used to execute the query. * If this parameter is not given, the `mongo` application component will be used. * @return integer number of records + * @throws Exception on failure. */ public function count($q = '*', $db = null) { $cursor = $this->buildCursor($db); - return $cursor->count(); + $token = 'Counting: ' . Json::encode($cursor->info()); + Yii::info($token, __METHOD__); + try { + Yii::beginProfile($token, __METHOD__); + $result = $cursor->count(); + Yii::endProfile($token, __METHOD__); + return $result; + } catch (\Exception $e) { + Yii::endProfile($token, __METHOD__); + throw new Exception($e->getMessage(), (int)$e->getCode(), $e); + } } /** diff --git a/tests/unit/extensions/mongo/CollectionTest.php b/tests/unit/extensions/mongo/CollectionTest.php index bc13b2e..a50177d 100644 --- a/tests/unit/extensions/mongo/CollectionTest.php +++ b/tests/unit/extensions/mongo/CollectionTest.php @@ -45,6 +45,7 @@ class CollectionTest extends MongoTestCase /** * @depends testInsert + * @depends testFind */ public function testFindAll() { @@ -55,7 +56,11 @@ class CollectionTest extends MongoTestCase ]; $id = $collection->insert($data); - $rows = $collection->findAll(); + $cursor = $collection->find(); + $rows = []; + foreach ($cursor as $row) { + $rows[] = $row; + } $this->assertEquals(1, count($rows)); $this->assertEquals($id, $rows[0]['_id']); } @@ -129,7 +134,7 @@ class CollectionTest extends MongoTestCase $count = $collection->remove(['_id' => $id]); $this->assertEquals(1, $count); - $rows = $collection->findAll(); + $rows = $this->findAll($collection); $this->assertEquals(0, count($rows)); } @@ -151,7 +156,7 @@ class CollectionTest extends MongoTestCase $count = $collection->update(['_id' => $id], $newData); $this->assertEquals(1, $count); - list($row) = $collection->findAll(); + list($row) = $this->findAll($collection); $this->assertEquals($newData['name'], $row['name']); } @@ -221,7 +226,7 @@ class CollectionTest extends MongoTestCase $this->assertEquals('mapReduceOut', $result); $outputCollection = $this->getConnection()->getCollection($result); - $rows = $outputCollection->findAll(); + $rows = $this->findAll($outputCollection); $expectedRows = [ [ '_id' => 1, diff --git a/tests/unit/extensions/mongo/MongoTestCase.php b/tests/unit/extensions/mongo/MongoTestCase.php index 27b7b13..e344109 100644 --- a/tests/unit/extensions/mongo/MongoTestCase.php +++ b/tests/unit/extensions/mongo/MongoTestCase.php @@ -103,4 +103,21 @@ class MongoTestCase extends TestCase } } } + + /** + * Finds all records in collection. + * @param \yii\mongo\Collection $collection + * @param array $condition + * @param array $fields + * @return array rows + */ + protected function findAll($collection, $condition = [], $fields = []) + { + $cursor = $collection->find($condition, $fields); + $result = []; + foreach ($cursor as $data) { + $result[] = $data; + } + return $result; + } } \ No newline at end of file