Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB: Use save() to update an existing document in a collection

everybody. I love manga. And now I am learning to love mongo too :-)

There is an explanation of how to use save() to update an existing document in a collection in MongoDB PHP? but I couldn't apply it to the PHP's "reality" :-)

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

Here's my test code:

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

The fact is that in the PHP example save() overwrites the object while in the JS example it updates it. I wish I can reproduce in PHP the same as in JS.

Thanks in advance.

like image 939
Roger Avatar asked Jan 01 '11 12:01

Roger


1 Answers

These examples aren't doing the same thing ...

In the JS examples you declared the object mongo

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

Then, you modified the same object to add type ...

> mongo.type = "database";

In the PHP example you declared TWO objects ...

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

This would be like doing the following in the JS shell ...

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

So apples is a different object/document from oranges ... hence when you run save() and pass the NEW object it totally overwrites the old object.

Your update() worked fine because you searched for the object ...

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

Then ran the update on that object; passing the new field instead of passing a new object to replace it ...

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

In the JS examples you only had one object so it basically appended it on the update instead of replacing it.

Correct PHP Code

The following PHP would replicate what you were doing in the JS shell ...

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

?>

Note: I'd strongly recommend you don't set your own object _id's and instead let the driver do it for you as I did in the example above.

like image 56
Justin Jenkins Avatar answered Oct 12 '22 10:10

Justin Jenkins