Home > OS >  MongoDb update if exists?
MongoDb update if exists?

Time:11-26

i am trying the logic ( insert if not exists , but if exists update the records )

i am new to MongoDB , but i use to do that with mysql , is it possible to achieve this using mongoDB ?

here is my code so far which is working well in case ( insert if not exists ) but not in ( update if exists )

$db = new MongoDB\Client($conn);
    $collection = $db->auth->users;
        
        $collection->createIndex(
            array( "username" => 1 ),
            array( "unique" => true )
        );
        
    $document = array(
        "title" => "Mraaxs",
        "fullname" => "John C12344",
        "username" => "user1",
        "age" => 22
    );
    
    $collection->updateOne(
        array("username" => $document["username"]),
        array('$setOnInsert' => $document),
        array("upsert" => true)
    );

CodePudding user response:

Most likely you need to change $setOnInsert to $set.

According to the documentation for $setOnInsert:

If an update operation with upsert: true results in an insert of a document, then $setOnInsert assigns the specified values to the fields in the document. If the update operation does not result in an insert, $setOnInsert does nothing.

So it behaves exactly as you described. $setOnInsert works for "insert if not exists" and does nothing for "update if exists".

$set will always update/put data into the document.

Here is a good example for your case from the documentation, using both $set and $setOnInsert.

db.products.updateOne(
  { _id: 1 },
  {
     $set: { item: "apple" },
     $setOnInsert: { defaultQty: 100 }
  },
  { upsert: true }
)

When the upsert parameter is true db.collection.updateOne()
 - creates a new document
 - applies the $set operation
 - applies the $setOnInsert operation

The products collection contains the newly-inserted document:

{ "_id" : 1, "item" : "apple", "defaultQty" : 100 }

So the solution will be:

... 
$collection->updateOne(
    array("username" => $document["username"]),
    array('$set' => $document),
    array("upsert" => true)
);

Note: optionally, you can use $setOnInsert to store created_at for new documents:

$collection->updateOne(
    array("username" => $document["username"]),
    array('$set' => $document, '$setOnInsert' => ['created_at' => time()]),
    array("upsert" => true)
);
  • Related