Skip to content

DOCSP-35957: Retrieve guide #2722

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
merged 26 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from 9 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
3 changes: 3 additions & 0 deletions docs/index.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Laravel MongoDB
:titlesonly:
:maxdepth: 1

/install
/retrieve
/quick-start
/eloquent-models
/query-builder
Expand Down Expand Up @@ -50,6 +52,7 @@ Fundamentals
To learn how to perform the following tasks by using the {+odm-short+},
see the following content:

- :ref:`laravel-fundamentals-retrieve`
- :ref:`laravel-eloquent-models`
- :ref:`laravel-query-builder`
- :ref:`laravel-user-authentication`
Expand Down
360 changes: 360 additions & 0 deletions docs/retrieve.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,360 @@
.. _laravel-fundamentals-retrieve:

==============
Retrieve Data
==============

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

.. meta::
:keywords: find one, find many, code example

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

Overview
--------

In this guide, you can learn how to use the Laravel package to perform **find operations**
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion:

I think "Laravel MongoDB" (the odm-short source constant) could be more consistent with the product name:

Suggested change
In this guide, you can learn how to use the Laravel package to perform **find operations**
In this guide, you can learn how to use the {+odm-short+} to perform **find operations**

on your MongoDB collections. Find operations allow you to retrieve documents based on
criteria that you specify.

This guide shows you how to perform the following tasks:

- :ref:`laravel-retrieve-matching`
- :ref:`laravel-retrieve-all`
- :ref:`Modify Find Operation Behavior <laravel-modify-find>`

Prerequisites
-------------

Complete the :ref:`Quick Start <laravel-quick-start>` tutorial before running the examples in this
guide.

After completing the Quick Start, ensure that your MongoDB deployment and Laravel application
satisfy the following requirements:

- Your Atlas MongoDB deployment contains the Atlas sample data
- ``Movie.php`` file contains a ``Movie`` model to represent the ``movies`` collection
- ``MovieController.php`` file contains a ``show()`` function to run database operations
- ``browse_movies.blade.php`` file contains HTML code to display the results of database
operations
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion:

I think the "Prerequisites" heading should describe a condition/state rather than provide instructions. One potential solution could be to replace the heading title with "Before You Get Started" and explain the following similar to this:

"To run the code in this guide, you need to complete the Quick Start tutorial, which includes setting up a MongoDB Atlas instance with sample data and the following files in your Laravel web application:

  • Movie.php, which contains the Movie model that ...
    "


The following sections describe how to edit the files in your Laravel application to run
the code examples and view the expected output.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
the code examples and view the expected output.
the find operation code examples and view the expected output.


.. _laravel-retrieve-matching:

Retrieve Documents that Match a Query
-------------------------------------

You can retrieve documents that match a set of criteria by passing a query filter to the ``where()``
method. A query filter specifies field value requirements and instructs the find operation
to only return documents that meet these requirements. To run the query, call the ``where()``
method on an Eloquent model or query builder that represents your collection.

You can pass the following types of query filters to the ``where()`` method:
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion:

I think the description of the "types" in "types of query filters" is missing from the list items. I think describing the list items directly like the following would help guide the reader:

"You can use one of the following "where()" method calls to build a query:"


- ``where('<field name>', <value>)``: instructs MongoDB to return documents that match
Copy link
Member

Choose a reason for hiding this comment

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

I find it more explicit if the context of the function is provided. Otherwise they can think the function where is global.

Suggested change
- ``where('<field name>', <value>)``: instructs MongoDB to return documents that match
- ``Model::where('<field name>', <value>)``: instructs MongoDB to return documents that match

the exact value for the specified field name

- ``where('<field name>', '<comparison operator>', <value>)``: instructs MongoDB to
return documents in which the field values meet the comparison criteria

To apply multiple sets of criteria to the find operation, you can chain a series
of ``where()`` methods together.

.. _laravel-retrieve-eloquent:

Use Eloquent Models to Retrieve Documents
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can use Laravel's Eloquent object-relational mapper (ORM) to create models that represent
MongoDB collections. To retrieve documents from a collection, call the ``where()`` method
on the collection's corresponding Eloquent model.

This example calls two ``where()`` methods on the ``Movie`` Eloquent model to retrieve
documents that meet the following criteria:

- ``year`` field has a value of ``2010``
- ``imdb.rating`` nested field has a value greater than ``8.5``

.. important:: Required File Changes

To run the code example, you must edit the ``MovieController.php`` file in your
Laravel Quick Start application. Copy the code example and paste it into the ``show()``
function, replacing any existing code inside this function.

.. io-code-block::
:copyable: true

.. input::
:language: php

return view('browse_movies', [
'movies' => Movie::where('year', 2010)
->where('imdb.rating', '>', 8.5)
->get()
]);

.. output::
:language: none
:visible: false

Title: Inception
Year: 2010
Runtime: 148
IMDB Rating: 8.8
IMDB Votes: 1294646
Plot: A thief who steals corporate secrets through use of dream-sharing
technology is given the inverse task of planting an idea into the mind of a CEO.

Title: Senna
Year: 2010
Runtime: 106
IMDB Rating: 8.6
IMDB Votes: 41904
Plot: A documentary on Brazilian Formula One racing driver Ayrton Senna, who won the
F1 world championship three times before his death at age 34.

.. _laravel-retrieve-query-builder:

Use Laravel Queries to Retrieve Documents
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can use Laravel's database query builder to run find operations instead of using Eloquent
models. To run the database query, import the ``DB`` facade into your controller file and use
Laravel's query builder syntax.

The following example uses Laravel's query builder to retrieve documents in which the value
of the ``imdb.votes`` nested field is greater than ``1300000``.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion:

No change necessary, but I think "1300000" can be difficult to read because of how long the number is. If you happen to have a different criteria/value to filter by that uses less lengthy values, I think that might be better.


.. important:: Required File Changes

To run the code example, you must make the following changes to your Laravel Quick Start
application:

- Copy the code example and paste it into the ``show()`` function in your ``MovieController.php`` file
- Add the ``use Illuminate\Support\Facades\DB`` use statement to your ``MovieController.php``
file
- Replace ``DB_CONNECTION=mysql`` with ``DB_CONNECTION=mongodb`` in your ``.env`` file
- Replace the contents of your ``browse_movies.blade.php`` file with the following code:

.. code-block:: php

<!DOCTYPE html>
<html>
<head>
<title>Browse Movies</title>
</head>
<body>
<h2>Movies</h2>

@forelse ($movies as $movie)
<p>
Title: {{ $movie['title'] }}<br>
Year: {{ $movie['year'] }}<br>
Runtime: {{ $movie['runtime'] }}<br>
IMDB Rating: {{ $movie['imdb']['rating'] }}<br>
IMDB Votes: {{ $movie['imdb']['votes'] }}<br>
Plot: {{ $movie['plot'] }}<br>
</p>
@empty
<p>No results</p>
@endforelse

</body>
</html>

.. io-code-block::
:copyable: true

.. input::
:language: php

return view('browse_movies', [
'movies' => DB::collection('movies')
->where('imdb.votes', '>', 1300000)
->get()
]);

.. output::
:language: none
:visible: false

Title: The Shawshank Redemption
Year: 1994
Runtime: 142
IMDB Rating: 9.3
IMDB Votes: 1513145
Plot: Two imprisoned men bond over a number of years, finding solace and eventual redemption
through acts of common decency.

Title: The Dark Knight
Year: 2008
Runtime: 152
IMDB Rating: 9
IMDB Votes: 1495351
Plot: When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the
caped crusader must come to terms with one of the greatest psychological tests of his ability to
fight injustice.

.. _laravel-retrieve-all:

Retrieve All Documents in a Collection
--------------------------------------

You can retrieve documents without specifying a query filter, which returns all
documents in a collection.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion:

I think it can be easier to understand the requirement by introducing the task first and then how to solve for it. E.g.

"You can retrieve all documents (task) in a collection by omitting the query filter (solution)."


To retrieve all documents, call the ``get()`` method on an Eloquent model that represents
your collection. Alternatively, you can use the ``get()`` method's alias ``all()`` to perform
the same operation.

.. _laravel-retrieve-all-example:

Retrieve All Documents
~~~~~~~~~~~~~~~~~~~~~~

Use the following syntax to run a find operation that matches all documents:

.. code-block:: php

$movies = Movie::get();
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion:

I think "To retrieve all documents" on line 271 repeats the task in the previous sentence and should be omitted.

Related to this suggestion, I think the subheading is unnecessary because it duplicates the top-level heading and there's no other subheading (I expected to see both Eloquent Models and Laravel Queries similar to the previous top-level haeding).


.. warning::

The ``movies`` collection in the Atlas sample dataset contains a large amount of data.
Retrieving and displaying all documents in this collection might cause your web
application to time out.

.. _laravel-modify-find:

Modify Behavior
---------------

You can modify the results of a find operation by chaining the following methods
to ``where()``:

- ``skip()``: sets the number of documents to skip when returning results
- ``take()``: sets the total number of documents to return
- ``first()``: returns the first document that matches the query filter

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion:
I think the subheadings could be introduced, e.g.
"The following sections show examples of how to use these methods."

Skip and Limit Results
~~~~~~~~~~~~~~~~~~~~~~

The following example queries for documents in which the ``year`` value is ``1999``.
The operation skips the first ``2`` matching documents and outputs a total of ``3``
documents.

.. important:: Required File Changes

To run the code example, you must edit the ``MovieController.php`` file in your
Laravel Quick Start application. Copy the code example and paste it into the ``show()``
function, replacing any existing code inside this function.

.. io-code-block::
:copyable: true

.. input::
:language: php

return view('browse_movies', [
'movies' => Movie::where('year', 1999)
->skip(2)
->take(3)
->get()
]);

.. output::
:language: none
:visible: false

Title: Three Kings
Year: 1999
Runtime: 114
IMDB Rating: 7.2
IMDB Votes: 130677
Plot: In the aftermath of the Persian Gulf War, 4 soldiers set out to steal gold
that was stolen from Kuwait, but they discover people who desperately need their help.

Title: Toy Story 2
Year: 1999
Runtime: 92
IMDB Rating: 7.9
IMDB Votes: 346655
Plot: When Woody is stolen by a toy collector, Buzz and his friends vow to rescue him,
but Woody finds the idea of immortality in a museum tempting.

Title: Beowulf
Year: 1999
Runtime: 95
IMDB Rating: 4
IMDB Votes: 9296
Plot: A sci-fi update of the famous 6th Century poem. In a beseiged land, Beowulf must
battle against the hideous creature Grendel and his vengeance seeking mother.

.. _laravel-retrieve-one:

Retrieve Only One Result
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion:

I think "Return the First Result" could be more descriptive since the section doesn't describe how to retrieve any other type of a single result (such as the last result).

Applies to the description contained in this section.

~~~~~~~~~~~~~~~~~~~~~~~~

To retrieve only one document that matches a set of criteria, use the ``where()`` method
followed by the ``first()`` method. By default, the ``first()`` method returns the first
matching document according to the documents' natural order, or as they appear in the
database. If you apply a sort to the find operation, ``first()`` returns the first matching
document according to the sorted order.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion:

I think it would be better to recommend a consistent sort order before describing natural ordering.

E.g. "Use the sort() method when you use the first() to get consistent results when you query on a unique value. If you omit the sort() method, MongoDB returns the matching documents according to the documents' natural order."


The following example returns one document in which the value of the ``runtime`` field
is ``30``.

.. important:: Required File Changes

To run the code example, you must edit the ``MovieController.php`` file in your
Laravel Quick Start application. Copy the code example and paste it into the ``show()``
function, replacing any existing code inside this function.

.. io-code-block::
:copyable: true

.. input::
:language: php

return view('browse_movies', [
'movies' => Movie::where('runtime', 30)
->first()
]);

.. output::
:language: none
:visible: false

Title: Statues also Die
Year: 1953
Runtime: 30
IMDB Rating: 7.6
IMDB Votes: 620
Plot: A documentary of black art.

.. tip::

To learn more about sorting, see the following resources:

- :manual:`Natural order </reference/glossary/#std-term-natural-order>`
in the Server manual glossary
- `Ordering, Grouping, Limit and Offset
<https://laravel.com/docs/10.x/queries#ordering-grouping-limit-and-offset>`__ in the Laravel
documentation

.. _laravel-addtl-info:

Additional Information
----------------------

To learn more about other query methods in {+odm-short+}, see the :ref:`laravel-query-builder`
page.