diff --git a/docs/fundamentals/write-operations.txt b/docs/fundamentals/write-operations.txt index 349372923..2e87677d1 100644 --- a/docs/fundamentals/write-operations.txt +++ b/docs/fundamentals/write-operations.txt @@ -9,7 +9,7 @@ Write Operations :values: tutorial .. meta:: - :keywords: insert, insert one, code example, mass assignment, eloquent model + :keywords: insert, insert one, update, update one, upsert, code example, mass assignment, eloquent model .. contents:: On this page :local: @@ -129,7 +129,6 @@ multiple instances of a ``Concert`` model as MongoDB documents. This bulk insert method reduces the number of calls your application needs to make to save the documents. - When the ``insert()`` method succeeds, it returns the value ``1``. If it fails, it throws an exception. @@ -156,7 +155,8 @@ Modify Documents In this section, you can learn how to modify documents in your MongoDB collection from your Laravel application. Use update operations to modify -existing documents or to insert a document if none match the search criteria. +existing documents or to insert a document if none match the search +criteria. You can persist changes on an instance of an Eloquent model or use Eloquent's fluent syntax to chain an update operation on methods that @@ -166,6 +166,7 @@ This section provides examples of the following update operations: - :ref:`Update a document ` - :ref:`Update multiple documents ` +- :ref:`Update or insert in a single operation ` .. _laravel-modify-documents-update-one: @@ -191,7 +192,7 @@ of the model and calling its ``save()`` method: When the ``save()`` method succeeds, the model instance on which you called the method contains the updated values. -If the operation fails, {+odm-short+} assigns the model instance a null value. +If the operation fails, {+odm-short+} assigns the model instance a ``null`` value. The following example shows how to update a document by chaining methods to retrieve and update the first matching document: @@ -241,10 +242,72 @@ and update them: When the ``update()`` method succeeds, the operation returns the number of documents updated. -If the retrieve part of the call does not match any documents in MongoDB, -{+odm-short+} returns the following error: +If the retrieve part of the call does not match any documents in the +collection, {+odm-short+} returns the following error: .. code-block:: none :copyable: false Error: Call to a member function update() on null + +.. _laravel-modify-documents-upsert: + +Update or Insert in a Single Operation +-------------------------------------- + +An **upsert** operation lets you perform an update or insert in a single +operation. This operation streamlines the task of updating a document or +inserting one if it does not exist. + +To specify an upsert in an ``update()`` method, set the ``upsert`` option to +``true`` as shown in the following code example: + +.. code-block:: php + :emphasize-lines: 4 + :copyable: false + + YourModel::where(/* match criteria */) + ->update( + [/* update data */], + ['upsert' => true]); + +When the ``update()`` method is chained to a query, it performs one of the +following actions: + +- If the query matches documents, the ``update()`` method modifies the matching + documents. +- If the query matches zero documents, the ``update()`` method inserts a + document that contains the update data and the equality match criteria data. + +Upsert Example +~~~~~~~~~~~~~~ + +This example shows how to pass the ``upsert`` option to the ``update()`` +method to perform an update or insert in a single operation. Click the +:guilabel:`VIEW OUTPUT` button to see the example document inserted when no +matching documents exist: + +.. io-code-block:: + + .. input:: /includes/fundamentals/write-operations/WriteOperationsTest.php + :language: php + :dedent: + :emphasize-lines: 4 + :start-after: begin model upsert + :end-before: end model upsert + + .. output:: + :language: json + :visible: false + + { + "_id": "660c...", + "performer": "Jon Batiste", + "venue": "Radio City Music Hall", + "genres": [ + "R&B", + "soul" + ], + "ticketsSold": 4000, + "updated_at": ... + } diff --git a/docs/includes/fundamentals/write-operations/WriteOperationsTest.php b/docs/includes/fundamentals/write-operations/WriteOperationsTest.php index a868c1fe8..5f759ae6b 100644 --- a/docs/includes/fundamentals/write-operations/WriteOperationsTest.php +++ b/docs/includes/fundamentals/write-operations/WriteOperationsTest.php @@ -214,4 +214,28 @@ public function testModelUpdateMultiple(): void $this->assertEquals(0, $result->ticketsSold); } } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testModelUpsert(): void + { + require_once __DIR__ . '/Concert.php'; + Concert::truncate(); + + // begin model upsert + Concert::where(['performer' => 'Jon Batiste', 'venue' => 'Radio City Music Hall']) + ->update( + ['genres' => ['R&B', 'soul'], 'ticketsSold' => 4000], + ['upsert' => true], + ); + // end model upsert + + $result = Concert::first(); + + $this->assertInstanceOf(Concert::class, $result); + $this->assertEquals('Jon Batiste', $result->performer); + $this->assertEquals(4000, $result->ticketsSold); + } }