2010-12-13 16 views
11

ist es möglich, die neue/aktualisierte _id nach der Abfrage zu bekommen? Beispielcode:get mongodb _id Objekt nach Upsert mit PHP

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

$ key ist nicht das neue/alte _id Objekt hält und ich nehme an, dass $ Daten werden auch nicht, weil seine nur eine Anweisung.

Antwort

16

Ja - Es ist möglich, eine einzige Abfrage zu verwenden.

MongoDB enthält einen findAndModify Befehl, der ein Dokument automatisch ändern und zurückgeben kann (standardmäßig gibt es das Dokument zurück, bevor es geändert wurde).

Die PHP-Treiber enthalten keine bequeme Methode für diese auf die Collection-Klasse (noch - Check-out this bug), aber es kann immer noch verwendet werden (beachten Sie, dass meine PHP ist schrecklich, so kann ich sehr gut gemacht haben ein Syntaxfehler im folgenden Ausschnitt):

$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']; 
+0

ahh - die 'findAndModify' ich es so selten benutze ich es immer vergessen existiert :) - Es ist gut, gelegentlich falsch bewiesen zu werden;) – gnarf

+0

@gnarf: Keine Sorge.Was mich merkwürdig findet ist, dass es keine Möglichkeit gibt, die _id automatisch in PHP zu bekommen - ich bin an die Python-Treiber gewöhnt, die die _id auf jedem [upsert] zurückgeben (http://api.mongodb.org/) Python/1.9% 2B/api/pymongo/Sammlung.html # pymongo.collection.Collection.save) – Cameron

15

Nur falls jemand über diese Frage stolpert wie ich, Mongo den Eingangs-Array tatsächlich ändern, wenn Sie MongoCollection-> save() nennen; - Anhängen der ID an das Ende. Also, wenn Sie anrufen:

$test = array('test'=>'testing'); 
mongocollection->save($test); 
echo $test['_id']; 

Sie das Mongo-ID für das Objekt haben.

+3

Ich weiß, dass dies auch auf die 'insert()' Funktion funktioniert. – Failpunk

+1

Fantastisch. Ich kann keinen Sinn darin sehen, den allzu komplexen 'findAndModify' zu verwenden, anstatt einen traditionellen' save' zu ​​verwenden, wenn es ein Standard ist, kein Schnickschnack, 'upsert'. – Nucleon

+0

Aha! Ich habe mich gefragt, warum es keinen Weg gab, die '_id' für einen Upsert in PHP zu bekommen ... Dies sollte die akzeptierte Antwort sein. – Cameron

1

Sie können fsync auch in einem update/upsert auf true festlegen, um die _id-Eigenschaft an das Objekt zurückzugeben, das an das Update übergeben wurde.

+1

Es scheint, dass es nicht funktioniert. – Oleg

3

Ich stieß auf dieses Problem und arbeitete daran, indem ich die _id nach dem Upsert abrief. Ich dachte, ich würde einige meiner Erkenntnisse hinzufügen, falls sie für jemanden nützlich sind, der hier nach Informationen sucht.

Wenn die Upsert Ergebnisse in einem neuen Dokument in der Sammlung erstellt wird, enthält das zurückgegebene Objekt die _id (hier ist ein print_r eines Beispiels):

Array 

(

[updatedExisting] => 0 

[upserted] => MongoId Object 
    (
     [$id] => 506dc50614c11c6ebdbc39bc 
    ) 

[n] => 1 
[connectionId] => 275 
[fsyncFiles] => 7 
[err] => 
[ok] => 1 
) 

Sie die _id von diesem erhalten kann:

$id = (string)$obj['upserted']; 

Wenn das Upsert jedoch zu einem vorhandenen Dokument führte, das aktualisiert wird, enthält das zurückgegebene Objekt _id nicht.

1

diesen Geben Sie einen Schuss:

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 die übergebene kann sagen $id null ist, ein frisches MongoId erstellt wird, sonst ist es wandelt nur die bestehenden $id zu einem MongoId Objekt.

hoffe, das hilft: D

1

Die Update-Methode ein Array mit der ID des Dokuments UPSERTED zurückgibt:

Array 
(
    [ok] => 1 
    [nModified] => 0 
    [n] => 1 
    [err] => 
    [errmsg] => 
    [upserted] => MongoId Object 
     (
      [$id] => 5511da18c8318aa1701881dd 
     ) 
    [updatedExisting] => 
)