Skip to content

DOCSP-35949 write operations upsert #2815

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 69 additions & 6 deletions docs/fundamentals/write-operations.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -166,6 +166,7 @@ This section provides examples of the following update operations:

- :ref:`Update a document <laravel-modify-documents-update-one>`
- :ref:`Update multiple documents <laravel-modify-documents-update-multiple>`
- :ref:`Update or insert in a single operation <laravel-modify-documents-upsert>`

.. _laravel-modify-documents-update-one:

Expand All @@ -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:
Expand Down Expand Up @@ -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": ...
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}