Skip to content

Commit 74067ee

Browse files
committed
PHP-1314: Implement Collection::findOneAndReplace()
1 parent f41ed65 commit 74067ee

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

examples/write.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,17 @@
125125

126126
$result = $collection->deleteMany(array("citizen" => "Iceland"));
127127
printf("Deleted: %d (out of expected 2)\n", $result->getNumRemoved());
128+
} catch(Exception $e) {
129+
printf("Caught exception '%s', on line %d\n", $e->getMessage(), __LINE__);
130+
exit;
131+
}
132+
133+
try {
134+
echo "FindOneAndReplace\n";
135+
$result = $collection->findOneAndReplace($spassky, $kasparov, array("upsert" => true));
136+
echo "Kasparov\n";
137+
var_dump($result);
138+
128139
} catch(Exception $e) {
129140
printf("Caught exception '%s', on line %d\n", $e->getMessage(), __LINE__);
130141
exit;

src/MongoDB/Collection.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ class Collection {
1818
const UPDATE = 0x02;
1919
const DELETE = 0x04;
2020

21+
const FIND_ONE_AND_RETURN_BEFORE = 0x01;
22+
const FIND_ONE_AND_RETURN_AFTER = 0x02;
23+
2124
protected $manager;
2225
protected $rp;
2326
protected $wc;
@@ -364,6 +367,88 @@ protected function _massageAggregateOptions($options) { /* {{{ */
364367
return $options;
365368
} /* }}} */
366369

370+
/* {{{ findAndModify */
371+
372+
function findOneAndReplace(array $filter, array $replacement, array $options = array()) { /* {{{ */
373+
if (key($replacement)[0] == '$') {
374+
throw new \RuntimeException("First key in \$replacement must NOT be a \$operator");
375+
}
376+
377+
$options = array_merge($this->getFindOneAndReplaceOptions(), $options);
378+
$options = $this->_massageFindAndModifyOptions($options, $replacement);
379+
380+
$cmd = array(
381+
"findandmodify" => $this->collname,
382+
"query" => $filter,
383+
) + $options;
384+
385+
$doc = $this->_runCommand($this->dbname, $cmd)->getResponseDocument();
386+
if ($doc["ok"]) {
387+
return $doc["value"];
388+
}
389+
390+
throw $this->_generateCommandException($doc);
391+
} /* }}} */
392+
function getFindOneAndReplaceOptions() { /* {{{ */
393+
return array(
394+
395+
/**
396+
* The maximum amount of time to allow the query to run.
397+
*
398+
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
399+
*/
400+
"maxTimeMS" => 0,
401+
402+
/**
403+
* Limits the fields to return for all matching documents.
404+
*
405+
* @see http://docs.mongodb.org/manual/tutorial/project-fields-from-query-results
406+
*/
407+
"projection" => array(),
408+
409+
/**
410+
* When ReturnDocument.After, returns the replaced or inserted document rather than the original.
411+
* Defaults to ReturnDocument.Before.
412+
*
413+
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
414+
*/
415+
"returnDocument" => self::FIND_ONE_AND_RETURN_BEFORE,
416+
417+
/**
418+
* Determines which document the operation modifies if the query selects multiple documents.
419+
*
420+
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
421+
*/
422+
"sort" => array(),
423+
424+
/**
425+
* When true, findAndModify creates a new document if no document matches the query. The
426+
* default is false.
427+
*
428+
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
429+
*/
430+
"upsert" => false,
431+
);
432+
433+
} /* }}} */
434+
435+
436+
protected function _massageFindAndModifyOptions($options, $update = array()) { /* {{{ */
437+
$ret = array(
438+
"sort" => $options["sort"],
439+
"new" => isset($options["returnDocument"]) ? $options["returnDocument"] == self::FIND_ONE_AND_RETURN_AFTER : false,
440+
"fields" => $options["projection"],
441+
"upsert" => isset($options["upsert"]) ? $options["upsert"] : false,
442+
);
443+
if ($update) {
444+
$ret["update"] = $update;
445+
} else {
446+
$ret["remove"] = true;
447+
}
448+
449+
return $ret;
450+
} /* }}} */
451+
/* }}} */
367452

368453
protected function _generateCommandException($doc) { /* {{{ */
369454
if ($doc["errmsg"]) {

0 commit comments

Comments
 (0)