1

I have to update lots of documents on MongoDB and I would like to do this in one operation with the server.

On a relational database such as MYSQL, I would do something like this:

$mysql = new MySQLi($host, $user, $pwd, $db, $port);
$q = "INSERT INTO table (idField, field) VALUES ";

foreach($elements as $el) {
  $q .= "({$el->id}, {$el->field}),";
}

$q = substr($q, 0, -1) . " ON DUPLICATE KEY UPDATE field = VALUES(field)";
$mysql->query($q);

Is there a possibility to do the same thing also in MongoDB? At the moment I have something like this:

$mongo = new MongoDB\Client("mongodb://{$host}:{$port}");
$col = $mongo->selectDatabase($db)->selectCollection($collectionName);

foreach($elements as $el) {
  $col->updateOne(array("id" => $el->id), array("field" => $el->field));
}

But this would cause a lot of connections to the database, causing a very slow process for billions of rows.

EDIT:

The following is an example of the starting data set:

{idField: 1, field: "A"}
{idField: 2, field: "B"}
{idField: 3, field: "C"}

Then I'd like to modify the field where idField is 1 to Alpha and a fieldAdded with Aleph, 2 to Beta and add Bet, 3 to Gamma and add Ghimel, obtaining the following resulting set:

{idField: 1, field: "Alpha", fieldAdded: "Aleph"}
{idField: 2, field: "Beta", fieldAdded: "Bet"}
{idField: 3, field: "Gamma", fieldAdded: "Ghimel"}

Is it possible to do so with just one request to the database?

oniramarf
  • 843
  • 1
  • 11
  • 27
  • 1
    Are you selecting all documents in the collection or a subset and if subset what is the selection criteria? Also, do you only want to change the fields if they exist or also add the ones that don't? If anything is nested could you please show basic structure. – DaveStSomeWhere Feb 05 '19 at 18:31
  • @DaveStSomeWhere Actually, yeah. I want to add fields that do not exist. I'm going to change the example with that. There's a selection criterion also, but I suppose that if I have the id field, it is not important when doing the update, isn't it? – oniramarf Feb 06 '19 at 09:16

1 Answers1

1

Use the bulkWrite method to do a bulk update as follows

$ops = array();      

foreach ($elements as $el) {  
    $update = [
        'updateOne' => [
            [ 'id' => $el->id ], 
            [ '$set' => [ 'field' => $el->field ] ]
        ]
    ];          
    array_push($ops, $update);                        
}

$result = $col->bulkWrite($ops);
echo $result->getModifiedCount();
chridam
  • 100,957
  • 23
  • 236
  • 235
  • I just changed the example because starting from a relational example, I didn't think that I was actually adding new fields to the document. This would work even if I add new fields? – oniramarf Feb 06 '19 at 09:21