get mongodb _id object after upsert with php
Yes -- It is possible using a single query.
MongoDB includes a findAndModify
command that can atomically modify a document and return it (by default it actually returns the document before it's been modified).
The PHP drivers don't include a convenient method for this on the collection class (yet -- check out this bug), but it can still be used (note that my PHP is terrible, so I may very well have made a syntax error in the following snippet):
$key = array( 'something' => 'unique' );$data = array( '$inc' => array( 'someint' => 1 ) );$result = $mongodb->db->command( array( 'findAndModify' => 'collection', 'query' => $key, 'update' => $data, 'new' => true, # To get back the document after the upsert 'upsert' => true, 'fields' => array( '_id' => 1 ) # Only return _id field) );$id = $result['value']['_id'];
Just in case someone stumbles across this question like I did, Mongo will actually modify the input array when you call MongoCollection->save(); - appending the id to the end.So, if you call:
$test = array('test'=>'testing');mongocollection->save($test);echo $test['_id'];
You will have the mongo id for that object.
I ran into this issue and worked around it by querying back the _id after the upsert. I thought I'd add some of my findings in case they're useful to anyone who comes here searching for info.
When the upsert results in a new document being created in the collection, the returned object contains the _id (here's a print_r of an example):
Array([updatedExisting] => 0[upserted] => MongoId Object ( [$id] => 506dc50614c11c6ebdbc39bc )[n] => 1[connectionId] => 275[fsyncFiles] => 7[err] => [ok] => 1)
You can get the _id from this:
$id = (string)$obj['upserted'];
However, if the upsert resulted in an existing document being updated then the returned object does not contain _id.