bernhardh
bernhardh

Reputation: 3309

Upsert many documents in MongoDB and php

I try to import data from an external source into my mongodb with php. Every row from the external data is one mongodb document. Every row has an unique id called uid.

Now I am trying the following: I want to insert a new row, if no document with the same uid exists already (Upsert).

For a single document, I would do the following:

$collection->updateOne(
    ["uid" => "2"],
    ['$set' => [
        "newfield" => date("Y-m-d H:i:s"),
        "name" => "Test"
    ]],
    [
        "upsert" => true
    ]
);

Step 1:

Is it possible to override the complete document, not just set specific fields? Something like this:

$collection->updateOne(
    ["uid" => "2"],
    [
        "newfield" => date("Y-m-d H:i:s"),
        "name" => "Test"
    ],
    [
        "upsert" => true
    ]
);

This is not working, since i get a First key in $update argument is not an update operator error. How to do it?

Step 2

For performance reasons, I want to use insertMany or updateMany function to bulk upsert multiple documents.

But what filter do I need for updateMany:

$db->updateMany(
    [???????],
    [
        "newfield" => date("Y-m-d H:i:s"),
        "name" => "XXX"
    ],
    [
        "upsert" => true
    ]
);

Upvotes: 4

Views: 4779

Answers (1)

Alex Blex
Alex Blex

Reputation: 37048

The questions are totally independent.

The first:

Use update with multi: false (which is default) instead of updateOne. The former allows to replaces an existing document entirely.

The second:

updateMany doesn't work this way. It is more like update with multi: true - it applies update operations to all documents that match the filter. When used with upsert: true the filter fields should be uniquely indexed to avoid multiple upserts.

If you want to perform multiple upserts with individual filters in one go, you can use bulk update:

$bulk = new MongoDB\Driver\BulkWrite(['ordered' => false]);
$bulk->update(["uid" => "2"], [
    "newfield" => date("Y-m-d H:i:s"),
    "name" => "Test"
]]);
$bulk->update(["uid" => "3"], [
    "newfield" => date("Y-m-d H:i:s"),
    "name" => "Another Test"
]]);
$bulk->update(["uid" => "4"], [
    "newfield" => date("Y-m-d H:i:s"),
    "name" => "One more Test"
]]);
$result = $manager->executeBulkWrite('db.collection', $bulk, $writeConcern);

Please read the page behind the last link for limitations of bulk operations.

Upvotes: 3

Related Questions