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
}
/**
* Returns a a single document.
* Returns a single document.
* @param array $condition query condition
* @param array $fields fields to be selected
* @return array|null the single document. Null is returned if the query results in nothing.
......@@ -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.
* @param array|object $data data to be inserted.
* @param array $options list of options in format: optionName => optionValue.
......
......@@ -187,6 +187,60 @@ class CollectionTest extends MongoDbTestCase
$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
*/
......@@ -240,54 +294,54 @@ class CollectionTest extends MongoDbTestCase
$this->assertEquals($expectedRows, $rows);
}
/**
* @depends testMapReduce
*/
public function testMapReduceInline()
{
$collection = $this->getConnection()->getCollection('customer');
$rows = [
[
'name' => 'customer 1',
'status' => 1,
'amount' => 100,
],
[
'name' => 'customer 2',
'status' => 1,
'amount' => 200,
],
[
'name' => 'customer 2',
'status' => 2,
'amount' => 400,
],
[
'name' => 'customer 2',
'status' => 3,
'amount' => 500,
],
];
$collection->batchInsert($rows);
$result = $collection->mapReduce(
'function () {emit(this.status, this.amount)}',
'function (key, values) {return Array.sum(values)}',
['inline' => true],
['status' => ['$lt' => 3]]
);
$expectedRows = [
[
'_id' => 1,
'value' => 300,
],
[
'_id' => 2,
'value' => 400,
],
];
$this->assertEquals($expectedRows, $result);
}
/**
* @depends testMapReduce
*/
public function testMapReduceInline()
{
$collection = $this->getConnection()->getCollection('customer');
$rows = [
[
'name' => 'customer 1',
'status' => 1,
'amount' => 100,
],
[
'name' => 'customer 2',
'status' => 1,
'amount' => 200,
],
[
'name' => 'customer 2',
'status' => 2,
'amount' => 400,
],
[
'name' => 'customer 2',
'status' => 3,
'amount' => 500,
],
];
$collection->batchInsert($rows);
$result = $collection->mapReduce(
'function () {emit(this.status, this.amount)}',
'function (key, values) {return Array.sum(values)}',
['inline' => true],
['status' => ['$lt' => 3]]
);
$expectedRows = [
[
'_id' => 1,
'value' => 300,
],
[
'_id' => 2,
'value' => 400,
],
];
$this->assertEquals($expectedRows, $result);
}
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