Skip to content

DOCSP-35949: write operations - upsert #2813

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

Closed
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
25 changes: 25 additions & 0 deletions docs/fundamentals.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.. _laravel_fundamentals:

============
Fundamentals
============

.. facet::
:name: genre
:values: reference

.. meta::
:keywords: php framework, odm

.. toctree::
:titlesonly:
:maxdepth: 1

/fundamentals/read-operations
/fundamentals/write-operations

Learn how to use the {+odm-long+} to perform the following tasks:

- :ref:`Read Operations <laravel-fundamentals-read-ops>`
- :ref:`Write Operations <laravel-fundamentals-write-ops>`

7 changes: 4 additions & 3 deletions docs/retrieve.txt → docs/fundamentals/read-operations.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
.. _laravel-fundamentals-retrieve:
.. _laravel-fundamentals-read-ops:

==============
Retrieve Data
==============
===============
Read Operations
===============

.. facet::
:name: genre
Expand Down
319 changes: 319 additions & 0 deletions docs/fundamentals/write-operations.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,319 @@
.. _laravel-fundamentals-write-ops:

================
Write Operations
================

.. facet::
:name: genre
:values: tutorial

.. meta::
:keywords: insert, insert one, update, update one, upsert, code example, mass assignment, eloquent model

.. contents:: On this page
:local:
:backlinks: none
:depth: 2
:class: singlecol

Overview
--------

In this guide, you can learn how to use {+odm-short+} to perform
**write operations** on your MongoDB collections. Write operations include
inserting, updating, and deleting data based on specified criteria.

This guide shows you how to perform the following tasks:

- :ref:`laravel-fundamentals-insert-documents`
- :ref:`laravel-fundamentals-modify-documents`
- Delete Documents

.. _laravel-fundamentals-write-sample-model:

Sample Model
~~~~~~~~~~~~

The write operations in this guide reference the following Eloquent model class:

.. literalinclude:: /includes/fundamentals/write-operations/Concert.php
:language: php
:dedent:
:caption: Concert.php

.. tip::

The ``$fillable`` attribute lets you use Laravel mass assignment for insert
operations. To learn more about mass assignment, see :ref:`laravel-model-mass-assignment`
in the Eloquent Model Class documentation.

The ``$casts`` attribute instructs Laravel to convert attributes to common
data types. To learn more, see `Attribute Casting <https://laravel.com/docs/{+laravel-docs-version+}/eloquent-mutators#attribute-casting>`__
in the Laravel documentation.

.. _laravel-fundamentals-insert-documents:

Insert Documents
----------------

In this section, you can learn how to insert documents into MongoDB collections
from your Laravel application by using the {+odm-long+}.

When you insert the documents, ensure the data does not violate any
unique indexes on the collection. When inserting the first document of a
collection or creating a new collection, MongoDB automatically creates a
unique index on the ``_id`` field.

For more information on creating indexes on MongoDB collections by using the
Laravel schema builder, see the :ref:`laravel-eloquent-indexes` section
of the Schema Builder documentation.

To learn more about Eloquent models in {+odm-short+}, see the :ref:`laravel-eloquent-models`
section.

Insert a Document Examples
~~~~~~~~~~~~~~~~~~~~~~~~~~

These examples show how to use the ``save()`` Eloquent method to insert an
instance of a ``Concert`` model as a MongoDB document.

When the ``save()`` method succeeds, you can access the model instance on
which you called the method.

If the operation fails, the model instance is assigned a null value.

This example code performs the following actions:

- Creates a new instance of the ``Concert`` model
- Assigns string values to the ``performer`` and ``venue`` fields
- Assigns an array of strings to the ``genre`` field
- Assigns a number to the ``ticketsSold`` field
- Assigns a date to the ``performanceDate`` field by using the ``Carbon``
package
- Inserts the document by calling the ``save()`` method

.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php
:language: php
:dedent:
:start-after: begin model insert one
:end-before: end model insert one

You can retrieve the inserted document's ``_id`` value by accessing the model's
``id`` member, as shown in the following code example:

.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php
:language: php
:dedent:
:start-after: begin inserted id
:end-before: end inserted id

If you enable mass assignment by defining either the ``$fillable`` or
``$guarded`` attributes, you can use the Eloquent model ``create()`` method
to perform the insert in a single call, as shown in the following example:

.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php
:language: php
:dedent:
:start-after: begin model insert one mass assign
:end-before: end model insert one mass assign

To learn more about the Carbon PHP API extension, see the
:github:`Carbon <briannesbitt/Carbon>` GitHub repository.

Insert Multiple Documents Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This example shows how to use the ``insert()`` Eloquent method to insert
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.

The example code saves multiple models in a single call by passing them as
an array to the ``insert()`` method:

.. note::

This example wraps the dates in the `MongoDB\\BSON\\UTCDateTime <{+phplib-api+}/class.mongodb-bson-utcdatetime.php>`__
class to convert it to a type MongoDB can serialize because Laravel
skips attribute casting on bulk insert operations.

.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php
:language: php
:dedent:
:start-after: begin model insert many
:end-before: end model insert many

.. _laravel-fundamentals-modify-documents:

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 no documents match the search
criteria.

Eloquent lets you specify criteria to retrieve documents, perform updates on
the returned object collections, and save them.

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:

Update a Document Examples
~~~~~~~~~~~~~~~~~~~~~~~~~~

You can update a document in the following ways:

- Modify an instance of the model and save the changes by calling the ``save()``
method.
- Use the fluent syntax to retrieve a matching document and apply updates to
it by calling the ``update()`` method or other helper methods.

The following example shows how to update a document by modifying an instance
of the model and calling its ``save()`` method:

.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php
:language: php
:dedent:
:start-after: begin model update one save
:end-before: end model update one save

When the ``save()`` method succeeds, the model instance on which you called the
method.

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

The following example shows how to update a document by using fluent syntax to
retrieve the first match and apply updates to the matching document:

.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php
:language: php
:dedent:
:start-after: begin model update one fluent
:end-before: end model update one fluent

.. note::

The ``orderBy()`` call sorts the results by the ``_id`` field to
guarantee a consistent sort order. To learn more about sorting in MongoDB,
see the :manual:`Natural order </reference/glossary/#std-term-natural-order>`
glossary entry in the {+server-docs-name+}.

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 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-update-multiple:

Update Multiple Documents Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To perform an update on one or more documents, call the ``update()``
method on a collection of model objects. You can use the fluent syntax to
retrieve a collection of model objects that match your criteria and then
pass your updates to the ``update()`` method.

The following example shows how to chain calls to retrieve a collection of
model objects and apply updates to all matching documents:

.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php
:language: php
:dedent:
:start-after: begin model update multiple
:end-before: end model update multiple

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 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 updates 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. It also includes
example results in which it performs an insert.

The following example shows how to perform an update or insert in a single
operation by passing the ``upsert`` option to the ``update()`` method. The
example output shows the result if the match criteria passed to the
``where()`` method matches zero documents in the collection. Click the
:guilabel:`VIEW OUTPUT` button to see the document inserted by running the
code:

.. io-code-block::

.. input:: /includes/fundamentals/write-operations/WriteOperationsTest.php
:language: php
:dedent:
: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": ...
}

12 changes: 12 additions & 0 deletions docs/includes/fundamentals/write-operations/Concert.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace App\Models;

use MongoDB\Laravel\Eloquent\Model;

class Concert extends Model
{
protected $connection = 'mongodb';
protected $fillable = ['performer', 'venue', 'genres', 'ticketsSold', 'performanceDate'];
protected $casts = ['performanceDate' => 'datetime'];
}
Loading