2011-01-01 14 views
8

tutti. Adoro i manga. E ora sto imparando ad amare anche mongo :-)MongoDB: utilizzare save() per aggiornare un documento esistente in una raccolta

C'è una spiegazione di how to use save() to update an existing document in a collection in MongoDB PHP? ma non ho potuto applicarlo alla "realtà" del PHP :-)

> var mongo = db.things.findOne({name:"mongo"}); 
> print(tojson(mongo)); 
{"_id" : "497dab624ee47b3a675d2d9c" , "name" : "mongo"} 
> mongo.type = "database"; 
database 
> db.things.save(mongo); 
> db.things.findOne({name:"mongo"}); 
{"_id" : "497dab624ee47b3a675d2d9c" , "name" : "mongo" , "type" : "database"} 

Ecco il mio codice di prova:

<?php 
$a=array('_id'=>'test_a','field1'=>'anything'); 
$b=array('_id'=>'test_a','field2'=>'anything else'); 

$m=new Mongo(); 
$c=$m->db->test; 
$c->save($a); 
$c->save($b);//overwrites the previous record 

/* 
//With update() it works fine 
$filter=array('_id'=>'test_a'); 
$update=array('$set'=>array('field2'=>'anything else')); 
$c->update($filter,$update); 
//$c->save($filter,$update);//Also tried... 
*/ 

$f=$c->find(); 
echo $f->count()." found \n"; 
$i=iterator_to_array($f);//mongo cursos iterator 
$m->close();//disconnect mongo 

print_r($i); 
?> 

Il fatto è che l'esempio PHP save() sovrascrive l'oggetto mentre nell'esempio JS lo aggiorna. Vorrei poter riprodurre in PHP lo stesso di JS.

Grazie in anticipo.

+0

In http://www.mongodb.org/display/DOCS/Updating#Updating-ModifierOperations si dice che "save() fa un upsert se x ha un campo _id (x è un oggetto stile JSON e upsert significa aggiornamento se presente, inserire se mancante) ". – Roger

+0

Non vedo quale sia il problema, gli esempi JS e PHP non fanno la stessa cosa? Dicci cosa stai aspettando. Non aspettarti che configuriamo l'ambiente ed eseguiamo il tuo codice solo per vedere l'output. – Theo

+0

Grazie per la risposta. Se esegui l'esempio php, vedrai che save() sovrascrive l'oggetto mentre nell'esempio JS lo aggiorna. Vorrei poter riprodurre in PHP lo stesso di JS. – Roger

risposta

12

Questi esempi non stanno facendo la stessa cosa ...

Negli esempi JS si dichiara l'oggetto mongo

> var mongo = db.things.findOne({name:"mongo"}); 

Poi, si è modificato lo stesso oggetto aggiungere digitare ...

> mongo.type = "database"; 

Nel PHP esempio si dichiarò due oggetti ...

$a=array('_id'=>'test_a','field1'=>'anything'); 
$b=array('_id'=>'test_a','field2'=>'anything else'); 

Sarebbe come fare il seguente nella shell JS ...

> var apples = db.things.findOne({name:"mongo"}); 
> var orange = db.things.findOne({type:"database"}); 

Così mele è un oggetto/documento diverso da arance ... quindi quando si esegue save() e si passa l'oggetto NEW, esso sovrascrive totalmente il vecchio oggetto.

tuo update() funzionato bene perché hai cercato l'oggetto ...

$filter=array('_id'=>'test_a'); 

poi corse l'aggiornamento su quell'oggetto; passando il nuovo campo invece di passare un nuovo oggettosostituirlo ...

$update=array('$set'=>array('field2'=>'anything else')); 
$c->update($filter,$update); 

Negli esempi JS si aveva solo un oggetto quindi sostanzialmente aggiunto sul aggiornamento invece di sostituirlo.

corretta codice PHP

Il seguente PHP sarebbe replicare quello che stavi facendo nella shell JS ...

<?php 

$connection = new Mongo(); 
$db = $connection->foo; 
$collection = $db->testing; 

// create new object & save 
$a = array('color'=>'red'); 
$collection->save($a); 

// add type = fruit to existing object & save 
$a['type'] = 'fruit'; 
$collection->save($a); 

// print out results. 
echo "<pre>"; 
var_dump($collection->findOne(array("color" => "red"))); 
echo "</pre>"; 

?> 

Nota: Mi piacerebbe fortemente consiglia di non impostare il proprio oggetto _id 's e invece lasciare che il driver di farlo per voi come ho fatto nell'esempio di cui sopra.

+0

Justin, grazie per la tua risposta molto brillante. Nel mio esempio ho pensato che 'save()' veniva alimentato solo con i contenuti degli array, non considerando che '$ a' e' $ b' erano in realtà oggetti diversi. Infatti, nell'esempio JS, c'era un 'findOne()' prima del "upsert". Questo 'findOne()' appare nel PHP 'update()', come ben detto, in '$ filter = array ('_ id' => 'test_a');' così che qualunque cosa venga nel prossimo argomento sarà inserita in questo oggetto. Grazie per il tuo ultimo esempio, è stato perfetto. – Roger

+0

E sto dando da mangiare a Mongo con il mio solo '_id' per non ripetermi, perché ho bisogno di un modo univoco e semplice per identificare un valore per fare aggiornamenti futuri. Per me è stato naturale usare il campo '_id'. Tuttavia, se c'è una buona ragione per non farlo, sarei felice di metterlo in un altro campo e lasciare che Mongo decidesse a modo suo. Per favore, mi dica perché raccomandi di non usare il campo '_id'? – Roger

+0

Ottimo! Se ho risposto alla tua domanda, contrassegna questa come "risposta" in modo che abbia il grande segno di spunta verde accanto ad essa! –

Problemi correlati