Skip to content

Commit acec97f

Browse files
author
Chris Cho
authored
DOCSP-35946 write operations arrays (#2825)
* DOCSP-35948: Write operations - arrays
1 parent eb329d3 commit acec97f

File tree

2 files changed

+262
-2
lines changed

2 files changed

+262
-2
lines changed

docs/fundamentals/write-operations.txt

Lines changed: 171 additions & 2 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, update, update one, upsert, code example, mass assignment, eloquent model
12+
:keywords: insert, insert one, update, update one, upsert, code example, mass assignment, push, pull, eloquent model
1313

1414
.. contents:: On this page
1515
:local:
@@ -167,6 +167,7 @@ This section provides examples of the following update operations:
167167
- :ref:`Update a document <laravel-modify-documents-update-one>`
168168
- :ref:`Update multiple documents <laravel-modify-documents-update-multiple>`
169169
- :ref:`Update or insert in a single operation <laravel-modify-documents-upsert>`
170+
- :ref:`Update arrays in a document <laravel-modify-documents-arrays>`
170171

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

@@ -292,7 +293,6 @@ matching documents exist:
292293
.. input:: /includes/fundamentals/write-operations/WriteOperationsTest.php
293294
:language: php
294295
:dedent:
295-
:emphasize-lines: 4
296296
:start-after: begin model upsert
297297
:end-before: end model upsert
298298

@@ -311,3 +311,172 @@ matching documents exist:
311311
"ticketsSold": 4000,
312312
"updated_at": ...
313313
}
314+
315+
.. _laravel-modify-documents-arrays:
316+
317+
Update Arrays in a Document
318+
---------------------------
319+
320+
In this section, you can see examples of the following operations that
321+
update array values in a MongoDB document:
322+
323+
- :ref:`Add values to an array <laravel-modify-documents-add-array-values>`
324+
- :ref:`Remove values from an array <laravel-modify-documents-remove-array-values>`
325+
- :ref:`Update the value of an array element <laravel-modify-documents-update-array-values>`
326+
327+
These examples modify the sample document created by the following insert
328+
operation:
329+
330+
.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php
331+
:language: php
332+
:dedent:
333+
:start-after: begin array example document
334+
:end-before: end array example document
335+
336+
.. _laravel-modify-documents-add-array-values:
337+
338+
Add Values to an Array Example
339+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
340+
341+
This section shows how to use the ``push()`` method to add values to an array
342+
in a MongoDB document. You can pass one or more values to add and set the
343+
optional parameter ``unique`` to ``true`` to skip adding any duplicate values
344+
in the array. The following code example shows the structure of a ``push()``
345+
method call:
346+
347+
.. code-block:: none
348+
:copyable: false
349+
350+
YourModel::where(<match criteria>)
351+
->push(
352+
<field name>,
353+
[<values>], // array or single value to add
354+
unique: true); // whether to skip existing values
355+
356+
The following example shows how to add the value ``"baroque"`` to
357+
the ``genres`` array field of a matching document. Click the
358+
:guilabel:`VIEW OUTPUT` button to see the updated document:
359+
360+
.. io-code-block::
361+
362+
.. input:: /includes/fundamentals/write-operations/WriteOperationsTest.php
363+
:language: php
364+
:dedent:
365+
:start-after: begin model array push
366+
:end-before: end model array push
367+
368+
.. output::
369+
:language: json
370+
:visible: false
371+
372+
{
373+
"_id": "660eb...",
374+
"performer": "Mitsuko Uchida",
375+
"genres": [
376+
"classical",
377+
"dance-pop",
378+
379+
],
380+
"updated_at": ...,
381+
"created_at": ...
382+
}
383+
384+
385+
.. _laravel-modify-documents-remove-array-values:
386+
387+
Remove Values From an Array Example
388+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
389+
390+
This section shows how to use the ``pull()`` method to remove values from
391+
an array in a MongoDB document. You can pass one or more values to remove
392+
from the array. The following code example shows the structure of a
393+
``pull()`` method call:
394+
395+
.. code-block:: none
396+
:copyable: false
397+
398+
YourModel::where(<match criteria>)
399+
->pull(
400+
<field name>,
401+
[<values>]); // array or single value to remove
402+
403+
The following example shows how to remove array values ``"classical"`` and
404+
``"dance-pop"`` from the ``genres`` array field. Click the
405+
:guilabel:`VIEW OUTPUT` button to see the updated document:
406+
407+
.. io-code-block::
408+
409+
.. input:: /includes/fundamentals/write-operations/WriteOperationsTest.php
410+
:language: php
411+
:dedent:
412+
:start-after: begin model array pull
413+
:end-before: end model array pull
414+
415+
.. output::
416+
:language: json
417+
:visible: false
418+
419+
{
420+
"_id": "660e...",
421+
"performer": "Mitsuko Uchida",
422+
"genres": [],
423+
"updated_at": ...,
424+
"created_at": ...
425+
}
426+
427+
428+
.. _laravel-modify-documents-update-array-values:
429+
430+
Update the Value of an Array Element Example
431+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
432+
433+
This section shows how to use the ``$`` positional operator to update specific
434+
array elements in a MongoDB document. The ``$`` operator represents the first
435+
array element that matches the query. The following code example shows the
436+
structure of a positional operator update call on a single matching document:
437+
438+
439+
.. note::
440+
441+
Currently, {+odm-short+} offers this operation only on the ``DB`` facade
442+
and not on the Eloquent ORM.
443+
444+
.. code-block:: none
445+
:copyable: false
446+
447+
DB::connection('mongodb')
448+
->getCollection(<collection name>)
449+
->updateOne(
450+
<match criteria>,
451+
['$set' => ['<array field>.$' => <replacement value>]]);
452+
453+
454+
The following example shows how to replace the array value ``"dance-pop"``
455+
with ``"contemporary"`` in the ``genres`` array field. Click the
456+
:guilabel:`VIEW OUTPUT` button to see the updated document:
457+
458+
.. io-code-block::
459+
460+
.. input:: /includes/fundamentals/write-operations/WriteOperationsTest.php
461+
:language: php
462+
:dedent:
463+
:start-after: begin model array positional
464+
:end-before: end model array positional
465+
466+
.. output::
467+
:language: json
468+
:visible: false
469+
470+
{
471+
"_id": "660e...",
472+
"performer": "Mitsuko Uchida",
473+
"genres": [
474+
"classical",
475+
"contemporary"
476+
],
477+
"updated_at": ...,
478+
"created_at": ...
479+
}
480+
481+
To learn more about array update operators, see :manual:`Array Update Operators </reference/operator/update-array/>`
482+
in the {+server-docs-name+}.

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

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66

77
use App\Models\Concert;
88
use Carbon\Carbon;
9+
use Illuminate\Support\Facades\DB;
910
use MongoDB\BSON\UTCDateTime;
1011
use MongoDB\Laravel\Tests\TestCase;
1112

1213
use function count;
14+
use function in_array;
1315

1416
class WriteOperationsTest extends TestCase
1517
{
@@ -238,4 +240,93 @@ public function testModelUpsert(): void
238240
$this->assertEquals('Jon Batiste', $result->performer);
239241
$this->assertEquals(4000, $result->ticketsSold);
240242
}
243+
244+
/**
245+
* @runInSeparateProcess
246+
* @preserveGlobalState disabled
247+
*/
248+
public function testModelPushArray(): void
249+
{
250+
require_once __DIR__ . '/Concert.php';
251+
Concert::truncate();
252+
253+
// begin array example document
254+
Concert::create([
255+
'performer' => 'Mitsuko Uchida',
256+
'genres' => ['classical', 'dance-pop'],
257+
]);
258+
// end array example document
259+
260+
// begin model array push
261+
Concert::where('performer', 'Mitsuko Uchida')
262+
->push(
263+
'genres',
264+
['baroque'],
265+
);
266+
// end model array push
267+
268+
$result = Concert::first();
269+
270+
$this->assertInstanceOf(Concert::class, $result);
271+
$this->assertContains('baroque', $result->genres);
272+
}
273+
274+
/**
275+
* @runInSeparateProcess
276+
* @preserveGlobalState disabled
277+
*/
278+
public function testModelPullArray(): void
279+
{
280+
require_once __DIR__ . '/Concert.php';
281+
Concert::truncate();
282+
283+
Concert::create([
284+
'performer' => 'Mitsuko Uchida',
285+
'genres' => [ 'classical', 'dance-pop' ],
286+
]);
287+
288+
// begin model array pull
289+
Concert::where('performer', 'Mitsuko Uchida')
290+
->pull(
291+
'genres',
292+
['dance-pop', 'classical'],
293+
);
294+
// end model array pull
295+
296+
$result = Concert::first();
297+
298+
$this->assertInstanceOf(Concert::class, $result);
299+
$this->assertEmpty($result->genres);
300+
}
301+
302+
/**
303+
* @runInSeparateProcess
304+
* @preserveGlobalState disabled
305+
*/
306+
public function testModelPositional(): void
307+
{
308+
require_once __DIR__ . '/Concert.php';
309+
Concert::truncate();
310+
311+
Concert::create([
312+
'performer' => 'Mitsuko Uchida',
313+
'genres' => [ 'classical', 'dance-pop' ],
314+
]);
315+
316+
// begin model array positional
317+
$match = ['performer' => 'Mitsuko Uchida', 'genres' => 'dance-pop'];
318+
$update = ['$set' => ['genres.$' => 'contemporary']];
319+
320+
DB::connection('mongodb')
321+
->getCollection('concerts')
322+
->updateOne($match, $update);
323+
// end model array positional
324+
325+
$result = Concert::first();
326+
327+
$this->assertInstanceOf(Concert::class, $result);
328+
$this->assertContains('classical', $result->genres);
329+
$this->assertContains('contemporary', $result->genres);
330+
$this->assertFalse(in_array('dance-pop', $result->genres));
331+
}
241332
}

0 commit comments

Comments
 (0)