Skip to content
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
173 changes: 171 additions & 2 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, update, update one, upsert, code example, mass assignment, eloquent model
:keywords: insert, insert one, update, update one, upsert, code example, mass assignment, push, pull, eloquent model

.. contents:: On this page
:local:
Expand Down Expand Up @@ -167,6 +167,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>`
- :ref:`Update arrays in a document <laravel-modify-documents-arrays>`

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

Expand Down Expand Up @@ -292,7 +293,6 @@ matching documents exist:
.. input:: /includes/fundamentals/write-operations/WriteOperationsTest.php
:language: php
:dedent:
:emphasize-lines: 4
:start-after: begin model upsert
:end-before: end model upsert

Expand All @@ -311,3 +311,172 @@ matching documents exist:
"ticketsSold": 4000,
"updated_at": ...
}

.. _laravel-modify-documents-arrays:

Update Arrays in a Document
---------------------------

In this section, you can see examples of the following operations that
update array values in a MongoDB document:

- :ref:`Add values to an array <laravel-modify-documents-add-array-values>`
- :ref:`Remove values from an array <laravel-modify-documents-remove-array-values>`
- :ref:`Update the value of an array element <laravel-modify-documents-update-array-values>`

These examples modify the sample document created by the following insert
operation:

.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php
:language: php
:dedent:
:start-after: begin array example document
:end-before: end array example document

.. _laravel-modify-documents-add-array-values:

Add Values to an Array Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This section shows how to use the ``push()`` method to add values to an array
in a MongoDB document. You can pass one or more values to add and set the
optional parameter ``unique`` to ``true`` to skip adding any duplicate values
in the array. The following code example shows the structure of a ``push()``
method call:

.. code-block:: none
:copyable: false

YourModel::where(<match criteria>)
->push(
<field name>,
[<values>], // array or single value to add
unique: true); // whether to skip existing values

The following example shows how to add the value ``"baroque"`` to
the ``genres`` array field of a matching document. Click the
:guilabel:`VIEW OUTPUT` button to see the updated document:

.. io-code-block::

.. input:: /includes/fundamentals/write-operations/WriteOperationsTest.php
:language: php
:dedent:
:start-after: begin model array push
:end-before: end model array push

.. output::
:language: json
:visible: false

{
"_id": "660eb...",
"performer": "Mitsuko Uchida",
"genres": [
"classical",
"dance-pop",

],
"updated_at": ...,
"created_at": ...
}


.. _laravel-modify-documents-remove-array-values:

Remove Values From an Array Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This section shows how to use the ``pull()`` method to remove values from
an array in a MongoDB document. You can pass one or more values to remove
from the array. The following code example shows the structure of a
``pull()`` method call:

.. code-block:: none
:copyable: false

YourModel::where(<match criteria>)
->pull(
<field name>,
[<values>]); // array or single value to remove

The following example shows how to remove array values ``"classical"`` and
``"dance-pop"`` from the ``genres`` array field. Click the
Comment on lines +403 to +404
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

S: [nit] since single quotes are used in the code:

Suggested change
The following example shows how to remove array values ``"classical"`` and
``"dance-pop"`` from the ``genres`` array field. Click the
The following example shows how to remove array values ``'classical'`` and
``'dance-pop'`` from the ``genres`` array field. Click the

:guilabel:`VIEW OUTPUT` button to see the updated document:

.. io-code-block::

.. input:: /includes/fundamentals/write-operations/WriteOperationsTest.php
:language: php
:dedent:
:start-after: begin model array pull
:end-before: end model array pull

.. output::
:language: json
:visible: false

{
"_id": "660e...",
"performer": "Mitsuko Uchida",
"genres": [],
"updated_at": ...,
"created_at": ...
}


.. _laravel-modify-documents-update-array-values:

Update the Value of an Array Element Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This section shows how to use the ``$`` positional operator to update specific
array elements in a MongoDB document. The ``$`` operator represents the first
array element that matches the query. The following code example shows the
structure of a positional operator update call on a single matching document:


.. note::

Currently, {+odm-short+} offers this operation only on the ``DB`` facade
and not on the Eloquent ORM.

.. code-block:: none
:copyable: false

DB::connection('mongodb')
->getCollection(<collection name>)
->updateOne(
<match criteria>,
['$set' => ['<array field>.$' => <replacement value>]]);


The following example shows how to replace the array value ``"dance-pop"``
with ``"contemporary"`` in the ``genres`` array field. Click the
Comment on lines +454 to +455
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

S: same comment about single quotes as above:

Suggested change
The following example shows how to replace the array value ``"dance-pop"``
with ``"contemporary"`` in the ``genres`` array field. Click the
The following example shows how to replace the array value ``'dance-pop'``
with ``'contemporary'`` in the ``genres`` array field. Click the

:guilabel:`VIEW OUTPUT` button to see the updated document:

.. io-code-block::

.. input:: /includes/fundamentals/write-operations/WriteOperationsTest.php
:language: php
:dedent:
:start-after: begin model array positional
:end-before: end model array positional

.. output::
:language: json
:visible: false

{
"_id": "660e...",
"performer": "Mitsuko Uchida",
"genres": [
"classical",
"contemporary"
],
"updated_at": ...,
"created_at": ...
}

To learn more about array update operators, see :manual:`Array Update Operators </reference/operator/update-array/>`
in the {+server-docs-name+}.
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@

use App\Models\Concert;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use MongoDB\BSON\UTCDateTime;
use MongoDB\Laravel\Tests\TestCase;

use function count;
use function in_array;

class WriteOperationsTest extends TestCase
{
Expand Down Expand Up @@ -238,4 +240,93 @@ public function testModelUpsert(): void
$this->assertEquals('Jon Batiste', $result->performer);
$this->assertEquals(4000, $result->ticketsSold);
}

/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testModelPushArray(): void
{
require_once __DIR__ . '/Concert.php';
Concert::truncate();

// begin array example document
Concert::create([
'performer' => 'Mitsuko Uchida',
'genres' => ['classical', 'dance-pop'],
]);
// end array example document

// begin model array push
Concert::where('performer', 'Mitsuko Uchida')
->push(
'genres',
['baroque'],
);
// end model array push

$result = Concert::first();

$this->assertInstanceOf(Concert::class, $result);
$this->assertContains('baroque', $result->genres);
}

/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testModelPullArray(): void
{
require_once __DIR__ . '/Concert.php';
Concert::truncate();

Concert::create([
'performer' => 'Mitsuko Uchida',
'genres' => [ 'classical', 'dance-pop' ],
]);

// begin model array pull
Concert::where('performer', 'Mitsuko Uchida')
->pull(
'genres',
['dance-pop', 'classical'],
);
// end model array pull

$result = Concert::first();

$this->assertInstanceOf(Concert::class, $result);
$this->assertEmpty($result->genres);
}

/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testModelPositional(): void
{
require_once __DIR__ . '/Concert.php';
Concert::truncate();

Concert::create([
'performer' => 'Mitsuko Uchida',
'genres' => [ 'classical', 'dance-pop' ],
]);

// begin model array positional
$match = ['performer' => 'Mitsuko Uchida', 'genres' => 'dance-pop'];
$update = ['$set' => ['genres.$' => 'contemporary']];

DB::connection('mongodb')
->getCollection('concerts')
->updateOne($match, $update);
// end model array positional

$result = Concert::first();

$this->assertInstanceOf(Concert::class, $result);
$this->assertContains('classical', $result->genres);
$this->assertContains('contemporary', $result->genres);
$this->assertFalse(in_array('dance-pop', $result->genres));
}
}