2011-01-01 7 views
8

tout le monde. J'aime les mangas. Et maintenant j'apprends à aimer mongo aussi :-)MongoDB: Utilisez save() pour mettre à jour un document existant dans une collection

Il ya une explication de how to use save() to update an existing document in a collection in MongoDB PHP? mais je ne pouvais pas l'appliquer à la « réalité » :-)

> 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"} 

Voici mon code de test du PHP:

<?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); 
?> 

Le fait est que dans l'exemple PHP save() Ecrase le tout objet dans l'exemple JS, il le met à jour. J'aimerais pouvoir reproduire en PHP comme dans JS.

Merci d'avance.

+0

Dans http://www.mongodb.org/display/DOCS/Updating#Updating-ModifierOperations il est dit que "save() fait un upsert si x a un champ _id (x est un objet de style JSON et upsert signifie une mise à jour si présent, insérer s'il manque) ". – Roger

+0

Je ne vois pas quel est le problème, les exemples JS et PHP ne font-ils pas la même chose? Dites-nous ce que vous attendez. Ne vous attendez pas à ce que nous configurions l'environnement et exécutiez votre code juste pour voir la sortie. – Theo

+0

Merci pour la réponse. Si vous exécutez l'exemple php, vous verrez que save() remplace l'objet alors que dans l'exemple JS il le met à jour. J'aimerais pouvoir reproduire en PHP comme dans JS. – Roger

Répondre

12

Ces exemples ne font pas la même chose ...

Dans les exemples de JS vous avez déclaré l'objet mongo

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

Ensuite, vous avez modifié le même objet ajouter tapez ...

> mongo.type = "database"; 

Dans le exemple PHP vous avez déclaré deux objets ...

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

Ce serait comme faire ce qui suit dans la coquille JS ...

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

Alors pommes est un autre objet/document de oranges ... donc lorsque vous exécutez save() et que vous passez l'objet NEW il écrase totalement l'ancien objet.

Votre mise à jour() a bien fonctionné parce que vous avez cherché pour l'objet ...

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

puis a couru la mise à jour sur que cet objet; en passant le nouveau champ au lieu de passer un nouvel objet pour le remplacer ...

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

Dans les exemples JS vous aviez seulement un objet il ajouté essentiellement sur la mise à jour au lieu de le remplacer.

correct Code PHP

Le PHP ci-dessous reproduirait ce que vous faisiez dans la coquille 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>"; 

?> 

Remarque: Je fortement vous recommandons de ne pas définir votre propre objet _id de la place et laisser le conducteur faire pour vous comme je l'ai fait dans l'exemple ci-dessus.

+0

Justin, merci pour votre réponse très brillante. Dans mon exemple, je pensais que 'save()' était alimenté uniquement avec le contenu des tableaux, sans considérer que '$ a' et' $ b' étaient en réalité des objets différents. En fait, dans l'exemple JS, il y avait un 'findOne()' avant le "upsert". Ce 'findOne()' apparaît dans le PHP 'update()', comme vous l'avez dit, dans '$ filter = array ('_ id' => 'test_a');' de sorte que tout ce qui vient dans le prochain argument sera inséré dans cet objet. Merci pour votre dernier exemple, c'était parfait. – Roger

+0

Et je nourris Mongo avec mon seul '_id' afin de ne pas me répéter, car j'ai besoin d'un moyen unique et facile d'identifier une valeur afin de faire de futures mises à jour. C'était tout naturel pour moi d'utiliser le champ '_id'. Cependant, s'il y a une bonne raison de ne pas le faire, je le mettrais volontiers dans un autre domaine et laisserais Mongo décider de sa propre façon. Pourriez-vous me dire pourquoi vous recommandez de ne pas utiliser le champ '_id'? – Roger

+0

Super! Si j'ai répondu à votre question, veuillez la marquer comme la «réponse», de sorte qu'il y ait une grosse coche verte à côté de celle-ci! –

Questions connexes