Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get mongodb _id object after upsert with php

is it possible to get the new/updated _id after the query? example code:

$key = array( 'something' => 'unique' );
$data = array( '$inc' => array( 'someint' => 1 ) );
$mongodb->db->collection->update( $key, $data, array( 'upsert' => true ) );

$key is not holding the new/old _id object and i assume that $data will not either because its just an instruction.

like image 624
Toby Avatar asked Dec 13 '10 22:12

Toby


4 Answers

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'];
like image 128
Cameron Avatar answered Nov 03 '22 07:11

Cameron


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.

like image 33
Jesse Avatar answered Nov 03 '22 09:11

Jesse


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.

like image 3
laguru Avatar answered Nov 03 '22 07:11

laguru


Give this a shot :

function save($data, $id = null) {
    $mongo_id = new MongoId($id);
    $criteria = array('_id' => $mongo_id);
    // Wrap a '$set' around the passed data array for convenience
    $update = array('$set' => $data);
    $collection->update($criteria, $update, array('upsert' => true));
}

So lets say the passed $id is null, a fresh MongoId is created, otherwise it just converts the existing $id to a MongoId object.

Hope this helps :D

like image 1
aster1sk Avatar answered Nov 03 '22 08:11

aster1sk