Skip to content

Commit eb329d3

Browse files
author
Chris Cho
authored
DOCSP-35949 write operations upsert (#2815)
* DOCSP-35948: Write operations - upsert
1 parent 014c7f4 commit eb329d3

File tree

2 files changed

+93
-6
lines changed

2 files changed

+93
-6
lines changed

docs/fundamentals/write-operations.txt

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Write Operations
99
:values: tutorial
1010

1111
.. meta::
12-
:keywords: insert, insert one, code example, mass assignment, eloquent model
12+
:keywords: insert, insert one, update, update one, upsert, code example, mass assignment, eloquent model
1313

1414
.. contents:: On this page
1515
:local:
@@ -129,7 +129,6 @@ multiple instances of a ``Concert`` model as MongoDB documents. This bulk
129129
insert method reduces the number of calls your application needs to make
130130
to save the documents.
131131

132-
133132
When the ``insert()`` method succeeds, it returns the value ``1``.
134133

135134
If it fails, it throws an exception.
@@ -156,7 +155,8 @@ Modify Documents
156155

157156
In this section, you can learn how to modify documents in your MongoDB
158157
collection from your Laravel application. Use update operations to modify
159-
existing documents or to insert a document if none match the search criteria.
158+
existing documents or to insert a document if none match the search
159+
criteria.
160160

161161
You can persist changes on an instance of an Eloquent model or use
162162
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:
166166

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

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

@@ -191,7 +192,7 @@ of the model and calling its ``save()`` method:
191192
When the ``save()`` method succeeds, the model instance on which you called the
192193
method contains the updated values.
193194

194-
If the operation fails, {+odm-short+} assigns the model instance a null value.
195+
If the operation fails, {+odm-short+} assigns the model instance a ``null`` value.
195196

196197
The following example shows how to update a document by chaining methods to
197198
retrieve and update the first matching document:
@@ -241,10 +242,72 @@ and update them:
241242
When the ``update()`` method succeeds, the operation returns the number of
242243
documents updated.
243244

244-
If the retrieve part of the call does not match any documents in MongoDB,
245-
{+odm-short+} returns the following error:
245+
If the retrieve part of the call does not match any documents in the
246+
collection, {+odm-short+} returns the following error:
246247

247248
.. code-block:: none
248249
:copyable: false
249250

250251
Error: Call to a member function update() on null
252+
253+
.. _laravel-modify-documents-upsert:
254+
255+
Update or Insert in a Single Operation
256+
--------------------------------------
257+
258+
An **upsert** operation lets you perform an update or insert in a single
259+
operation. This operation streamlines the task of updating a document or
260+
inserting one if it does not exist.
261+
262+
To specify an upsert in an ``update()`` method, set the ``upsert`` option to
263+
``true`` as shown in the following code example:
264+
265+
.. code-block:: php
266+
:emphasize-lines: 4
267+
:copyable: false
268+
269+
YourModel::where(/* match criteria */)
270+
->update(
271+
[/* update data */],
272+
['upsert' => true]);
273+
274+
When the ``update()`` method is chained to a query, it performs one of the
275+
following actions:
276+
277+
- If the query matches documents, the ``update()`` method modifies the matching
278+
documents.
279+
- If the query matches zero documents, the ``update()`` method inserts a
280+
document that contains the update data and the equality match criteria data.
281+
282+
Upsert Example
283+
~~~~~~~~~~~~~~
284+
285+
This example shows how to pass the ``upsert`` option to the ``update()``
286+
method to perform an update or insert in a single operation. Click the
287+
:guilabel:`VIEW OUTPUT` button to see the example document inserted when no
288+
matching documents exist:
289+
290+
.. io-code-block::
291+
292+
.. input:: /includes/fundamentals/write-operations/WriteOperationsTest.php
293+
:language: php
294+
:dedent:
295+
:emphasize-lines: 4
296+
:start-after: begin model upsert
297+
:end-before: end model upsert
298+
299+
.. output::
300+
:language: json
301+
:visible: false
302+
303+
{
304+
"_id": "660c...",
305+
"performer": "Jon Batiste",
306+
"venue": "Radio City Music Hall",
307+
"genres": [
308+
"R&B",
309+
"soul"
310+
],
311+
"ticketsSold": 4000,
312+
"updated_at": ...
313+
}

docs/includes/fundamentals/write-operations/WriteOperationsTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,4 +214,28 @@ public function testModelUpdateMultiple(): void
214214
$this->assertEquals(0, $result->ticketsSold);
215215
}
216216
}
217+
218+
/**
219+
* @runInSeparateProcess
220+
* @preserveGlobalState disabled
221+
*/
222+
public function testModelUpsert(): void
223+
{
224+
require_once __DIR__ . '/Concert.php';
225+
Concert::truncate();
226+
227+
// begin model upsert
228+
Concert::where(['performer' => 'Jon Batiste', 'venue' => 'Radio City Music Hall'])
229+
->update(
230+
['genres' => ['R&B', 'soul'], 'ticketsSold' => 4000],
231+
['upsert' => true],
232+
);
233+
// end model upsert
234+
235+
$result = Concert::first();
236+
237+
$this->assertInstanceOf(Concert::class, $result);
238+
$this->assertEquals('Jon Batiste', $result->performer);
239+
$this->assertEquals(4000, $result->ticketsSold);
240+
}
217241
}

0 commit comments

Comments
 (0)