Commit ef12934b by Paul Klimov

Merge pull request #2613 from mongosoft/mongodb

add findAndModify() method to the Collection class
parents 2ecb79dc 1676d914
...@@ -260,7 +260,7 @@ class Collection extends Object ...@@ -260,7 +260,7 @@ class Collection extends Object
} }
/** /**
* Returns a a single document. * Returns a single document.
* @param array $condition query condition * @param array $condition query condition
* @param array $fields fields to be selected * @param array $fields fields to be selected
* @return array|null the single document. Null is returned if the query results in nothing. * @return array|null the single document. Null is returned if the query results in nothing.
...@@ -272,6 +272,32 @@ class Collection extends Object ...@@ -272,6 +272,32 @@ class Collection extends Object
} }
/** /**
* Updates a document and returns it.
* @param array $condition query condition
* @param array $update update criteria
* @param array $fields fields to be returned
* @param array $options list of options in format: optionName => optionValue.
* @return array|null the original document, or the modified document when $options['new'] is set.
* @throws Exception on failure.
* @see http://www.php.net/manual/en/mongocollection.findandmodify.php
*/
public function findAndModify($condition, $update, $fields = [], $options = [])
{
$condition = $this->buildCondition($condition);
$token = $this->composeLogToken('findAndModify', [$condition, $update, $fields, $options]);
Yii::info($token, __METHOD__);
try {
Yii::beginProfile($token, __METHOD__);
$result = $this->mongoCollection->findAndModify($condition, $update, $fields, $options);
Yii::endProfile($token, __METHOD__);
return $result;
} catch (\Exception $e) {
Yii::endProfile($token, __METHOD__);
throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
}
}
/**
* Inserts new data into collection. * Inserts new data into collection.
* @param array|object $data data to be inserted. * @param array|object $data data to be inserted.
* @param array $options list of options in format: optionName => optionValue. * @param array $options list of options in format: optionName => optionValue.
......
...@@ -187,6 +187,60 @@ class CollectionTest extends MongoDbTestCase ...@@ -187,6 +187,60 @@ class CollectionTest extends MongoDbTestCase
$this->assertNotEmpty($result[0]['items']); $this->assertNotEmpty($result[0]['items']);
} }
public function testFindAndModify()
{
$collection = $this->getConnection()->getCollection('customer');
$rows = [
[
'name' => 'customer 1',
'status' => 1,
'amount' => 100,
],
[
'name' => 'customer 2',
'status' => 1,
'amount' => 200,
],
];
$collection->batchInsert($rows);
// increment field
$result = $collection->findAndModify(['name' => 'customer 1'], ['$inc' => ['status' => 1]]);
$this->assertEquals('customer 1', $result['name']);
$this->assertEquals(1, $result['status']);
$newResult = $collection->findOne(['name' => 'customer 1']);
$this->assertEquals(2, $newResult['status']);
// $set and return modified document
$result = $collection->findAndModify(
['name' => 'customer 2'],
['$set' => ['status' => 2]],
[],
['new' => true]
);
$this->assertEquals('customer 2', $result['name']);
$this->assertEquals(2, $result['status']);
// Full update document
$data = [
'name' => 'customer 3',
'city' => 'Minsk'
];
$result = $collection->findAndModify(
['name' => 'customer 2'],
$data,
[],
['new' => true]
);
$this->assertEquals('customer 3', $result['name']);
$this->assertEquals('Minsk', $result['city']);
$this->assertTrue(!isset($result['status']));
// Test exceptions
$this->setExpectedException('\yii\mongodb\Exception');
$collection->findAndModify(['name' => 'customer 1'], ['$wrongOperator' => ['status' => 1]]);
}
/** /**
* @depends testBatchInsert * @depends testBatchInsert
*/ */
...@@ -240,54 +294,54 @@ class CollectionTest extends MongoDbTestCase ...@@ -240,54 +294,54 @@ class CollectionTest extends MongoDbTestCase
$this->assertEquals($expectedRows, $rows); $this->assertEquals($expectedRows, $rows);
} }
/** /**
* @depends testMapReduce * @depends testMapReduce
*/ */
public function testMapReduceInline() public function testMapReduceInline()
{ {
$collection = $this->getConnection()->getCollection('customer'); $collection = $this->getConnection()->getCollection('customer');
$rows = [ $rows = [
[ [
'name' => 'customer 1', 'name' => 'customer 1',
'status' => 1, 'status' => 1,
'amount' => 100, 'amount' => 100,
], ],
[ [
'name' => 'customer 2', 'name' => 'customer 2',
'status' => 1, 'status' => 1,
'amount' => 200, 'amount' => 200,
], ],
[ [
'name' => 'customer 2', 'name' => 'customer 2',
'status' => 2, 'status' => 2,
'amount' => 400, 'amount' => 400,
], ],
[ [
'name' => 'customer 2', 'name' => 'customer 2',
'status' => 3, 'status' => 3,
'amount' => 500, 'amount' => 500,
], ],
]; ];
$collection->batchInsert($rows); $collection->batchInsert($rows);
$result = $collection->mapReduce( $result = $collection->mapReduce(
'function () {emit(this.status, this.amount)}', 'function () {emit(this.status, this.amount)}',
'function (key, values) {return Array.sum(values)}', 'function (key, values) {return Array.sum(values)}',
['inline' => true], ['inline' => true],
['status' => ['$lt' => 3]] ['status' => ['$lt' => 3]]
); );
$expectedRows = [ $expectedRows = [
[ [
'_id' => 1, '_id' => 1,
'value' => 300, 'value' => 300,
], ],
[ [
'_id' => 2, '_id' => 2,
'value' => 400, 'value' => 400,
], ],
]; ];
$this->assertEquals($expectedRows, $result); $this->assertEquals($expectedRows, $result);
} }
public function testCreateIndex() public function testCreateIndex()
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment