2

i am trying to update several documents in mongodb with different values each.

In mysql I do something like this:

$objs = array(array('id'=>1,'lat'=>37.123,'lng'=>53.123),...,array('id'=>n,'lat'=>x,'lng'=>y));

$sql = "INSERT INTO objects (objectId,latitude,longitude) VALUES";
        foreach ($objs as $obj) {
            $id = $obj['id'];
            $lat = $obj['lat'];
            $lng = $obj['lng'];
            $sql .= "($id,$lat,$lng),";
        }
        $sql = substr_replace($sql ," ",-1);    
        $sql.= "ON DUPLICATE KEY UPDATE latitude=VALUES(latitude),longitude=VALUES(longitude)";

Now, is it possible to do it in mongodb?

xeraa
  • 10,456
  • 3
  • 33
  • 66
leojg
  • 1,156
  • 3
  • 16
  • 40
  • 1
    yes im doing it that way now, but i think it's quite inefficient becouse you have to access the db the same amount of times you need to edit it. While the sql way all the loops are made in the DB. – leojg May 20 '13 at 15:31

2 Answers2

4

This question has already been asked here: MongoDB: insert on duplicate key update

In mongodb you can use the upsert option on Update command. It's similar as ON DUPLICATE KEY UPDATE. Definition of upsert option:

A kind of update that either updates the first document matched in the provided query selector or, if no document matches, inserts a new document having the fields implied by the query selector and the update operation.

I have consulting the PHP Mongo Documentation. In example #2 of MongoCollection:Update command you have your response.

Example:

<?php
$objs = array(array('id'=>1,'lat'=>37.123,'lng'=>53.123), array('id'=>n,'lat'=>x,'lng'=>y));

foreach($objs as $obj)
{
    // Parameters: [1] Description of the objects to update. [2] The object with which to update the matching records. [3] Options 
    $collection->update(array("id" => $obj["id"]), $obj, array("upsert" => true));
}

?>
Community
  • 1
  • 1
Mentor Reka
  • 9,107
  • 1
  • 12
  • 8
  • Yes, basically im doing that way now, but is it the best way? Thanks for answering. – leojg May 20 '13 at 15:33
  • If this is the best (fast and reliable) way fair that you want, i don't know. But it what you need. I don't know other methods but would be interested to know if they exist. If you find one, post it here please :) – Mentor Reka May 21 '13 at 07:22
  • 1
    it's unreal do with one query? – xfg Oct 16 '16 at 07:16
1

If you're duplicate key in your SQL is referencing the ID field, then it would be as follows:

// Your big array thing from your example
$objs = array(array('id'=>1,'lat'=>37.123,'lng'=>53.123),...,array('id'=>n,'lat'=>x,'lng'=>y));
// Start a new MongoClient
$m = new MongoClient();
// Select the DB and Collection
$collection = $m->selectCollection('DBNAME', 'COLLECTIONNAME');
// Loop through $objs
foreach($objs as $obj) {
    $collection->update(
        // If we find a matching ID, update, else insert
        array('id' => $obj['id']), 
        // The data we're inserting
        $obj, 
        // specify the upsert flag, to create a new one if it can't find
        array('upsert' => true) 
    );
}

Basically, the update command (with upsert set to true) will either update an existing document that matches the first parameter of the update, or insert a new document. Mentor Reka's post talks more about how upserts work, but the code above should do exactly what you're looking for.

Community
  • 1
  • 1
Jesta
  • 1,458
  • 1
  • 13
  • 14