diff --git a/docs/eloquent-models/schema-builder.txt b/docs/eloquent-models/schema-builder.txt index 9fd845b55..39c6a9887 100644 --- a/docs/eloquent-models/schema-builder.txt +++ b/docs/eloquent-models/schema-builder.txt @@ -324,6 +324,8 @@ field: To learn more about these indexes, see :manual:`Index Properties ` in the {+server-docs-name+}. +.. _laravel-eloquent-geospatial-index: + Create a Geospatial Index ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/includes/query-builder/QueryBuilderTest.php b/docs/includes/query-builder/QueryBuilderTest.php new file mode 100644 index 000000000..40705102d --- /dev/null +++ b/docs/includes/query-builder/QueryBuilderTest.php @@ -0,0 +1,579 @@ +collection('movies') + ->insert(json_decode(file_get_contents(__DIR__ . '/sample_mflix.movies.json'), true)); + } + + protected function importTheaters(): void + { + $db = DB::connection('mongodb'); + + $db->collection('theaters') + ->insert(json_decode(file_get_contents(__DIR__ . '/sample_mflix.theaters.json'), true)); + + $db->collection('theaters') + ->raw() + ->createIndex(['location.geo' => '2dsphere']); + } + + protected function tearDown(): void + { + $db = DB::connection('mongodb'); + $db->collection('movies')->raw()->drop(); + $db->collection('theaters')->raw()->drop(); + + parent::tearDown(); + } + + public function testWhere(): void + { + // begin query where + $result = DB::connection('mongodb') + ->collection('movies') + ->where('imdb.rating', 9.3) + ->get(); + // end query where + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testOrWhere(): void + { + // begin query orWhere + $result = DB::connection('mongodb') + ->collection('movies') + ->where('year', 1955) + ->orWhere('title', 'Back to the Future') + ->get(); + // end query orWhere + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testAndWhere(): void + { + // begin query andWhere + $result = DB::connection('mongodb') + ->collection('movies') + ->where('imdb.rating', '>', 8.5) + ->where('year', '<', 1940) + ->get(); + // end query andWhere + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testWhereNot(): void + { + // begin query whereNot + $result = DB::connection('mongodb') + ->collection('movies') + ->whereNot('imdb.rating', '>', 2) + ->get(); + // end query whereNot + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testNestedLogical(): void + { + // begin query nestedLogical + $result = DB::connection('mongodb') + ->collection('movies') + ->where('imdb.rating', '>', 8.5) + ->where(function (Builder $query) { + return $query + ->where('year', 1986) + ->orWhere('year', 1996); + })->get(); + // end query nestedLogical + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testWhereBetween(): void + { + // begin query whereBetween + $result = DB::connection('mongodb') + ->collection('movies') + ->whereBetween('imdb.rating', [9, 9.5]) + ->get(); + // end query whereBetween + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testWhereNull(): void + { + // begin query whereNull + $result = DB::connection('mongodb') + ->collection('movies') + ->whereNull('runtime') + ->get(); + // end query whereNull + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testWhereIn(): void + { + // begin query whereIn + $result = DB::collection('movies') + ->whereIn('title', ['Toy Story', 'Shrek 2', 'Johnny English']) + ->get(); + // end query whereIn + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testWhereDate(): void + { + // begin query whereDate + $result = DB::connection('mongodb') + ->collection('movies') + ->whereDate('released', '2010-1-15') + ->get(); + // end query whereDate + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testLike(): void + { + // begin query like + $result = DB::collection('movies') + ->where('title', 'like', '%spider_man%') + ->get(); + // end query like + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testDistinct(): void + { + // begin query distinct + $result = DB::collection('movies') + ->distinct('year')->get(); + // end query distinct + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testGroupBy(): void + { + // begin query groupBy + $result = DB::collection('movies') + ->where('rated', 'G') + ->groupBy('runtime') + ->orderBy('runtime', 'asc') + ->get(['title']); + // end query groupBy + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testAggCount(): void + { + // begin aggregation count + $result = DB::collection('movies') + ->count(); + // end aggregation count + + $this->assertIsInt($result); + } + + public function testAggMax(): void + { + // begin aggregation max + $result = DB::collection('movies') + ->max('runtime'); + // end aggregation max + + $this->assertIsInt($result); + } + + public function testAggMin(): void + { + // begin aggregation min + $result = DB::collection('movies') + ->min('year'); + // end aggregation min + + $this->assertIsInt($result); + } + + public function testAggAvg(): void + { + // begin aggregation avg + $result = DB::collection('movies') + ->avg('imdb.rating'); + //->avg('year'); + // end aggregation avg + + $this->assertIsFloat($result); + } + + public function testAggSum(): void + { + // begin aggregation sum + $result = DB::collection('movies') + ->sum('imdb.votes'); + // end aggregation sum + + $this->assertIsInt($result); + } + + public function testAggWithFilter(): void + { + // begin aggregation with filter + $result = DB::collection('movies') + ->where('year', '>', 2000) + ->avg('imdb.rating'); + // end aggregation with filter + + $this->assertIsFloat($result); + } + + public function testOrderBy(): void + { + // begin query orderBy + $result = DB::collection('movies') + ->where('title', 'like', 'back to the future%') + ->orderBy('imdb.rating', 'desc') + ->get(); + // end query orderBy + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testSkip(): void + { + // begin query skip + $result = DB::collection('movies') + ->where('title', 'like', 'star trek%') + ->orderBy('year', 'asc') + ->skip(4) + ->get(); + // end query skip + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testProjection(): void + { + // begin query projection + $result = DB::collection('movies') + ->where('imdb.rating', '>', 8.5) + ->project([ + 'title' => 1, + 'cast' => ['$slice' => [1, 3]], + ]) + ->get(); + // end query projection + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testProjectionWithPagination(): void + { + // begin query projection with pagination + $resultsPerPage = 15; + $projectionFields = ['title', 'runtime', 'imdb.rating']; + + $result = DB::collection('movies') + ->orderBy('imdb.votes', 'desc') + ->paginate($resultsPerPage, $projectionFields); + // end query projection with pagination + + $this->assertInstanceOf(AbstractPaginator::class, $result); + } + + public function testExists(): void + { + // begin query exists + $result = DB::collection('movies') + ->exists('random_review', true); + // end query exists + + $this->assertIsBool($result); + } + + public function testAll(): void + { + // begin query all + $result = DB::collection('movies') + ->where('movies', 'all', ['title', 'rated', 'imdb.rating']) + ->get(); + // end query all + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testSize(): void + { + // begin query size + $result = DB::collection('movies') + ->where('directors', 'size', 5) + ->get(); + // end query size + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testType(): void + { + // begin query type + $result = DB::collection('movies') + ->where('released', 'type', 4) + ->get(); + // end query type + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testMod(): void + { + // begin query modulo + $result = DB::collection('movies') + ->where('year', 'mod', [2, 0]) + ->get(); + // end query modulo + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testWhereRegex(): void + { + // begin query whereRegex + $result = DB::connection('mongodb') + ->collection('movies') + ->where('title', 'REGEX', new Regex('^the lord of .*', 'i')) + ->get(); + // end query whereRegex + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testWhereRaw(): void + { + // begin query raw + $result = DB::collection('movies') + ->whereRaw([ + 'imdb.votes' => ['$gte' => 1000 ], + '$or' => [ + ['imdb.rating' => ['$gt' => 7]], + ['directors' => ['$in' => [ 'Yasujiro Ozu', 'Sofia Coppola', 'Federico Fellini' ]]], + ], + ])->get(); + // end query raw + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testElemMatch(): void + { + // begin query elemMatch + $result = DB::collection('movies') + ->where('writers', 'elemMatch', ['$in' => ['Maya Forbes', 'Eric Roth']]) + ->get(); + // end query elemMatch + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testCursorTimeout(): void + { + // begin query cursor timeout + $result = DB::collection('movies') + ->timeout(2) // value in seconds + ->where('year', 2001) + ->get(); + // end query cursor timeout + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + } + + public function testNear(): void + { + $this->importTheaters(); + + // begin query near + $results = DB::collection('theaters') + ->where('location.geo', 'near', [ + '$geometry' => [ + 'type' => 'Point', + 'coordinates' => [ + -86.6423, + 33.6054, + ], + ], + '$maxDistance' => 50, + ])->get(); + // end query near + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $results); + } + + public function testGeoWithin(): void + { + // begin query geoWithin + $results = DB::collection('theaters') + ->where('location.geo', 'geoWithin', [ + '$geometry' => [ + 'type' => 'Polygon', + 'coordinates' => [ + [ + [-72, 40], + [-74, 41], + [-72, 39], + [-72, 40], + ], + ], + ], + ])->get(); + // end query geoWithin + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $results); + } + + public function testGeoIntersects(): void + { + // begin query geoIntersects + $results = DB::collection('theaters') + ->where('location.geo', 'geoIntersects', [ + '$geometry' => [ + 'type' => 'LineString', + 'coordinates' => [ + [-73.600525, 40.74416], + [-72.600525, 40.74416], + ], + ], + ])->get(); + // end query geoIntersects + + $this->assertInstanceOf(\Illuminate\Support\Collection::class, $results); + } + + public function testGeoNear(): void + { + $this->importTheaters(); + + // begin query geoNear + $results = DB::collection('theaters')->raw( + function (Collection $collection) { + return $collection->aggregate([ + [ + '$geoNear' => [ + 'near' => [ + 'type' => 'Point', + 'coordinates' => [-118.34, 34.10], + ], + 'distanceField' => 'dist.calculated', + 'maxDistance' => 500, + 'includeLocs' => 'dist.location', + 'spherical' => true, + ], + ], + ]); + }, + )->toArray(); + // end query geoNear + + $this->assertIsArray($results); + $this->assertSame(8900, $results[0]['theaterId']); + } + + public function testUpsert(): void + { + // begin upsert + $result = DB::collection('movies') + ->where('title', 'Will Hunting') + ->update( + [ + 'plot' => 'An autobiographical movie', + 'year' => 1998, + 'writers' => [ 'Will Hunting' ], + ], + ['upsert' => true], + ); + // end upsert + + $this->assertIsInt($result); + } + + public function testIncrement(): void + { + // begin increment + $result = DB::collection('movies') + ->where('title', 'Field of Dreams') + ->increment('imdb.votes', 3000); + // end increment + + $this->assertIsInt($result); + } + + public function testDecrement(): void + { + // begin decrement + $result = DB::collection('movies') + ->where('title', 'Sharknado') + ->decrement('imdb.rating', 0.2); + // end decrement + + $this->assertIsInt($result); + } + + public function testPush(): void + { + // begin push + $result = DB::collection('movies') + ->where('title', 'Office Space') + ->push('cast', 'Gary Cole'); + // end push + + $this->assertIsInt($result); + } + + public function testPull(): void + { + // begin pull + $result = DB::collection('movies') + ->where('title', 'Iron Man') + ->pull('genres', 'Adventure'); + // end pull + + $this->assertIsInt($result); + } + + public function testUnset(): void + { + // begin unset + $result = DB::collection('movies') + ->where('title', 'Final Accord') + ->unset('tomatoes.viewer'); + // end unset + + $this->assertIsInt($result); + } +} diff --git a/docs/includes/query-builder/sample_mflix.movies.json b/docs/includes/query-builder/sample_mflix.movies.json new file mode 100644 index 000000000..57873754e --- /dev/null +++ b/docs/includes/query-builder/sample_mflix.movies.json @@ -0,0 +1,196 @@ +[ + { + "genres": [ + "Short" + ], + "runtime": 1, + "cast": [ + "Charles Kayser", + "John Ott" + ], + "title": "Blacksmith Scene", + "directors": [ + "William K.L. Dickson" + ], + "rated": "UNRATED", + "year": 1893, + "imdb": { + "rating": 6.2, + "votes": 1189, + "id": 5 + }, + "tomatoes": { + "viewer": { + "rating": 3, + "numReviews": 184, + "meter": 32 + } + } + }, + { + "genres": [ + "Short", + "Western" + ], + "runtime": 11, + "cast": [ + "A.C. Abadie", + "Gilbert M. 'Broncho Billy' Anderson", + "George Barnes", + "Justus D. Barnes" + ], + "title": "The Great Train Robbery", + "directors": [ + "Edwin S. Porter" + ], + "rated": "TV-G", + "year": 1903, + "imdb": { + "rating": 7.4, + "votes": 9847, + "id": 439 + }, + "tomatoes": { + "viewer": { + "rating": 3.7, + "numReviews": 2559, + "meter": 75 + } + } + }, + { + "genres": [ + "Short", + "Drama", + "Fantasy" + ], + "runtime": 14, + "rated": "UNRATED", + "cast": [ + "Martin Fuller", + "Mrs. William Bechtel", + "Walter Edwin", + "Ethel Jewett" + ], + "title": "The Land Beyond the Sunset", + "directors": [ + "Harold M. Shaw" + ], + "writers": [ + "Dorothy G. Shore" + ], + "year": 1912, + "imdb": { + "rating": 7.1, + "votes": 448, + "id": 488 + }, + "tomatoes": { + "viewer": { + "rating": 3.7, + "numReviews": 53, + "meter": 67 + } + } + }, + { + "genres": [ + "Short", + "Drama" + ], + "runtime": 14, + "cast": [ + "Frank Powell", + "Grace Henderson", + "James Kirkwood", + "Linda Arvidson" + ], + "title": "A Corner in Wheat", + "directors": [ + "D.W. Griffith" + ], + "rated": "G", + "year": 1909, + "imdb": { + "rating": 6.6, + "votes": 1375, + "id": 832 + }, + "tomatoes": { + "viewer": { + "rating": 3.6, + "numReviews": 109, + "meter": 73 + } + } + }, + { + "genres": [ + "Animation", + "Short", + "Comedy" + ], + "runtime": 7, + "cast": [ + "Winsor McCay" + ], + "title": "Winsor McCay, the Famous Cartoonist of the N.Y. Herald and His Moving Comics", + "directors": [ + "Winsor McCay", + "J. Stuart Blackton" + ], + "writers": [ + "Winsor McCay (comic strip \"Little Nemo in Slumberland\")", + "Winsor McCay (screenplay)" + ], + "year": 1911, + "imdb": { + "rating": 7.3, + "votes": 1034, + "id": 1737 + }, + "tomatoes": { + "viewer": { + "rating": 3.4, + "numReviews": 89, + "meter": 47 + } + } + }, + { + "genres": [ + "Comedy", + "Fantasy", + "Romance" + ], + "runtime": 118, + "cast": [ + "Meg Ryan", + "Hugh Jackman", + "Liev Schreiber", + "Breckin Meyer" + ], + "title": "Kate & Leopold", + "directors": [ + "James Mangold" + ], + "writers": [ + "Steven Rogers (story)", + "James Mangold (screenplay)", + "Steven Rogers (screenplay)" + ], + "year": 2001, + "imdb": { + "rating": 6.3, + "votes": 59951, + "id": 35423 + }, + "tomatoes": { + "viewer": { + "rating": 3, + "numReviews": 189426, + "meter": 62 + } + } + } +] diff --git a/docs/includes/query-builder/sample_mflix.theaters.json b/docs/includes/query-builder/sample_mflix.theaters.json new file mode 100644 index 000000000..b8d55381c --- /dev/null +++ b/docs/includes/query-builder/sample_mflix.theaters.json @@ -0,0 +1,39 @@ +[ + { + "theaterId": 1000, + "location": { + "address": { + "street1": "340 W Market", + "city": "Bloomington", + "state": "MN", + "zipcode": "55425" + }, + "geo": { + "type": "Point", + "coordinates": [ + -93.24565, + 44.85466 + ] + } + } + }, + { + "theaterId": 8900, + "location": { + "address": { + "street1": "6801 Hollywood Blvd", + "street2": null, + "city": "Hollywood", + "state": "CA", + "zipcode": "90028" + }, + "geo": { + "type": "Point", + "coordinates": [ + -118.340261, + 34.102593 + ] + } + } + } +] diff --git a/docs/query-builder.txt b/docs/query-builder.txt index 55b5762e4..9650df09b 100644 --- a/docs/query-builder.txt +++ b/docs/query-builder.txt @@ -9,590 +9,1116 @@ Query Builder :values: tutorial .. meta:: - :keywords: php framework, odm, code example + :keywords: code example, aggregation -The database driver plugs right into the original query builder. +.. contents:: On this page + :local: + :backlinks: none + :depth: 2 + :class: singlecol -When using MongoDB connections, you will be able to build fluent queries to -perform database operations. +Overview +-------- -For your convenience, there is a ``collection`` alias for ``table`` and -other MongoDB specific operators/operations. +In this guide, you can learn how to use the {+odm-short+} extension of +the Laravel query builder to work with a MongoDB database. The query builder +lets you use a single syntax and fluent interface to write queries for any +supported database. -.. code-block:: php - - $books = DB::collection('books')->get(); - - $hungerGames = - DB::collection('books') - ->where('name', 'Hunger Games') - ->first(); - -If you are familiar with `Eloquent Queries `__, -there is the same functionality. - -Available operations --------------------- - -**Retrieving all models** - -.. code-block:: php - - $users = User::all(); - -**Retrieving a record by primary key** - -.. code-block:: php - - $user = User::find('517c43667db388101e00000f'); - -**Where** - -.. code-block:: php - - $posts = - Post::where('author.name', 'John') - ->take(10) - ->get(); - -**OR Statements** - -.. code-block:: php - - $posts = - Post::where('votes', '>', 0) - ->orWhere('is_approved', true) - ->get(); - -**AND statements** - -.. code-block:: php - - $users = - User::where('age', '>', 18) - ->where('name', '!=', 'John') - ->get(); - -**NOT statements** - -.. code-block:: php - - $users = User::whereNot('age', '>', 18)->get(); - -**whereIn** - -.. code-block:: php +.. note:: - $users = User::whereIn('age', [16, 18, 20])->get(); + {+odm-short+} extends Laravel's query builder and Eloquent ORM, which can + run similar database operations. To learn more about retrieving documents + by using Eloquent models, see :ref:`laravel-fundamentals-retrieve`. -When using ``whereNotIn`` objects will be returned if the field is -non-existent. Combine with ``whereNotNull('age')`` to omit those documents. +Laravel provides a **facade** to access the query builder class ``DB``, which +lets you perform database operations. Facades, which are static interfaces to +classes, make the syntax more concise, avoid runtime errors, and improve +testability. -**whereBetween** +{+odm-short+} aliases the ``DB`` method ``table()`` as the ``collection()`` +method. Chain methods to specify commands and any constraints. Then, chain +the ``get()`` method at the end to run the methods and retrieve the results. +The following example shows the syntax of a query builder call: .. code-block:: php - $posts = Post::whereBetween('votes', [1, 100])->get(); + DB::collection('') + // chain methods by using the "->" object operator + ->get(); -**whereNull** +This guide provides examples of the following types of query builder operations: + +- :ref:`laravel-retrieve-query-builder` +- :ref:`laravel-modify-results-query-builder` +- :ref:`laravel-mongodb-read-query-builder` +- :ref:`laravel-mongodb-write-query-builder` + +Before You Get Started +---------------------- + +To run the code examples in this guide, complete the +:ref:`Quick Start ` tutorial to configure a web +application, load sample datasets into your MongoDB deployment, and +run the example code from a controller method. + +To perform read and write operations by using the query builder, import the +``Illuminate\Support\Facades\DB`` facade and compose your query. + +.. _laravel-retrieve-query-builder: + +Retrieve Matching Documents +--------------------------- + +This section includes query builder examples for read operations in the +following operator categories: + +- :ref:`Where method ` +- :ref:`Logical conditionals ` +- :ref:`Ranges and type checks ` +- :ref:`Pattern searches ` +- :ref:`Retrieve distinct values ` +- :ref:`Aggregations ` + +.. _laravel-query-builder-where-example: + +Where Method Example +~~~~~~~~~~~~~~~~~~~~ + +The following example shows how to use the ``where()`` query +builder method to retrieve documents from the ``movies`` collection +that contain an ``imdb.rating`` field value of exactly ``9.3``. Click the +:guilabel:`{+code-output-label+}` button to see the results returned +by the query: + +.. io-code-block:: + :copyable: true + + .. input:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query where + :end-before: end query where + + .. output:: + :language: json + :visible: false + + [ + { "title": "Cosmos", + "year": 1980, + "runtime": 60, + "imdb": { + "rating": 9.3, + "votes": 17174, + "id": 81846 + }, + "plot": "Astronomer Carl Sagan leads us on an engaging guided tour of the various elements and cosmological theories of the universe.", + ... + }, + { "title": "The Shawshank Redemption", + "year": 1994, + "runtime": 142, + "imdb": { + "rating": 9.3, + "votes": 1521105, + "id": 111161 + }, + "plot": "Two imprisoned men bond over a number of years, finding solace and eventual redemption through acts of common decency.", + ... + }, + { "title": "The Real Miyagi", + "year": 2015, + "runtime": 90, + "imdb": { + "rating": 9.3, + "votes": 41, + "id": 2313306 + }, + "plot": "The life of the greatest karate master of a generation.", + ... + } + ] + +.. _laravel-query-builder-logical-operations: + +Logical Conditional Operations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The examples in this section show the query builder syntax you +can use to perform the following logical conditional operations: + +- :ref:`Logical OR to match one or more conditions ` +- :ref:`Logical AND to match all conditions ` +- :ref:`Logical NOT to match the negation of the condition ` +- :ref:`Nested logical operator groups ` + +.. _laravel-query-builder-logical-or: + +Logical OR Example +^^^^^^^^^^^^^^^^^^ + +The following example shows how to chain the ``orWhere()`` +query builder method to retrieve documents from the +``movies`` collection that either match the ``year`` +value of ``1955`` or match the ``title`` value ``"Back to the Future"``: + +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query orWhere + :end-before: end query orWhere + +.. _laravel-query-builder-logical-and: + +Logical AND Example +^^^^^^^^^^^^^^^^^^^ + +The following example shows how to chain the ``where()`` +query builder method to retrieve documents from the +``movies`` collection that match both an ``imdb.rating`` +value greater than ``8.5`` and a ``year`` value of less than +``1940``: + +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query andWhere + :end-before: end query andWhere + +.. _laravel-query-builder-logical-not: + +Logical NOT Example +^^^^^^^^^^^^^^^^^^^ + +The following example shows how to call the ``whereNot()`` +query builder method to retrieve documents from the +``movies`` collection that match documents that do not have an ``imdb.rating`` +value greater than ``2``. This is equivalent to matching all documents +that have an ``imdb.rating`` of less than or equal to ``2``: + +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query whereNot + :end-before: end query whereNot + +.. _laravel-query-builder-logical-nested: + +Nested Logical Operator Group Example +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following example shows how to chain the ``where()`` +query builder method to retrieve documents from the +``movies`` collection that match both of the following +conditions. This example passes a closure as the first +parameter of the ``where()`` query builder method to group +the logical OR group: + +- ``imdb.rating`` value is greater than ``8.5`` +- ``year`` value is either ``1986`` or ``1996`` + +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query nestedLogical + :end-before: end query nestedLogical + +.. _laravel-query-builder-range-type: + +Ranges and Type Checks +~~~~~~~~~~~~~~~~~~~~~~ + +The examples in this section show the query builder syntax you can use to +match values by using the following range queries and type check operations: + +- :ref:`Values within a numerical range ` +- :ref:`Null or missing values ` +- :ref:`One or more values of a set ` +- :ref:`Match dates ` +- :ref:`Match a text pattern ` -.. code-block:: php +.. _laravel-query-builder-wherebetween: - $users = User::whereNull('age')->get(); +Numerical Range Example +^^^^^^^^^^^^^^^^^^^^^^^ -**whereDate** +The following example shows how to use the ``whereBetween()`` +query builder method to retrieve documents from the +``movies`` collection that contain an ``imdb.rating`` value +between ``9`` and ``9.5``: -.. code-block:: php +.. io-code-block:: + :copyable: true - $users = User::whereDate('birthday', '2021-5-12')->get(); + .. input:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query whereBetween + :end-before: end query whereBetween + + .. output:: + :language: none + :visible: false + + [ + { "title" "The Godfather", "imdb": { "rating": 9.2, "votes": 1038358, "id": 68646 }, ... }, + { "title": "Hollywood", "imdb": { "rating": 9.1, "votes": 511,"id": 80230 }, ... }, + { "title": "Cosmos", "imdb": { "rating": 9.3, "votes": 17174, "id": 81846 }, ... }, + ... + ] -The usage is the same as ``whereMonth`` / ``whereDay`` / ``whereYear`` / ``whereTime`` +.. _laravel-query-builder-null: + +Null or Missing Values Example +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following example shows how to use the ``whereNull()`` +query builder method to retrieve documents from the +``movies`` collection that omit a ``runtime`` value +or field: + +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query whereNull + :end-before: end query whereNull -**Advanced wheres** +.. _laravel-query-builder-wherein: -.. code-block:: php +One or More Values of a Set Example +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following example shows how to use the ``whereIn()`` +query builder method to retrieve documents from the +``movies`` collection that match at least one of the +``title`` values in the specified set: + +.. io-code-block:: + :copyable: true - $users = - User::where('name', 'John') - ->orWhere(function ($query) { - return $query - ->where('votes', '>', 100) - ->where('title', '<>', 'Admin'); - })->get(); + .. input:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query whereIn + :end-before: end query whereIn -**orderBy** + .. output:: + :language: json + :visible: false -.. code-block:: php + [ + { "title": "Toy Story", "year": 1995, "runtime": 81, ... }, + { "title": "Johnny English", "year": 2003, "runtime": 87, ... }, + { "title": "Shrek 2", "year" 2004, "runtime": 93, ... }, + ... + ] - $users = User::orderBy('age', 'desc')->get(); +.. _laravel-query-builder-wheredate: -**Offset & Limit (skip & take)** +Match Dates Example +^^^^^^^^^^^^^^^^^^^ -.. code-block:: php +The following example shows how to use the ``whereDate()`` +query builder method to retrieve documents from the +``movies`` collection that match the specified date of +``2010-1-15`` in the ``released`` field: - $users = - User::skip(10) - ->take(5) - ->get(); +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query whereDate + :end-before: end query whereDate + +.. _laravel-query-builder-pattern: -**groupBy** +Text Pattern Match Example +~~~~~~~~~~~~~~~~~~~~~~~~~~ -Selected columns that are not grouped will be aggregated with the ``$last`` -function. +The following example shows how to use the ``like`` query operator +with the ``where()`` query builder method to retrieve documents from the +``movies`` collection by using a specified text pattern. + +Text patterns can contain text mixed with the following +wildcard characters: + +- ``%`` which matches zero or more characters +- ``_`` which matches a single character + +.. io-code-block:: + :copyable: true + + .. input:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query like + :end-before: end query like + + .. output:: + :language: json + :visible: false + + [ + { "title": "Kiss of the Spider Woman", ... }, + { "title": "Spider-Man", ... }, + { "title": "Spider-Man 2", ...}, + ... + ] + +.. _laravel-query-builder-distinct: + +Retrieve Distinct Values +~~~~~~~~~~~~~~~~~~~~~~~~ + +The following example shows how to use the ``distinct()`` +query builder method to retrieve all the different values +of the ``year`` field for documents in the ``movies`` collections. + +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query distinct + :end-before: end query distinct + +.. _laravel-query-builder-aggregations: + +Aggregations +~~~~~~~~~~~~ + +The examples in this section show the query builder syntax you +can use to perform **aggregations**. Aggregations are operations +that compute values from a set of query result data. You can use +aggregations to compute and return the following information: + +- :ref:`Results grouped by common field values ` +- :ref:`Count the number of results ` +- :ref:`Maximum value of a field ` +- :ref:`Minimum value of a field ` +- :ref:`Average value of a field ` +- :ref:`Summed value of a field ` +- :ref:`Aggregate matched results ` + +.. _laravel-query-builder-aggregation-groupby: + +Results Grouped by Common Field Values Example +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following example shows how to use the ``groupBy()`` query builder method +to retrieve document data grouped by shared values of the ``runtime`` field. +This example chains the following operations to match documents from the +``movies`` collection that contain a ``rated`` value of ``G`` and include the +``title`` field of one movie for each distinct ``runtime`` value: + +- Match only documents that contain a ``rated`` field value of ``"G"`` by + using the ``where()`` method +- Group data by the distinct values of the ``runtime`` field, which is + assigned the ``_id`` field, by using the ``groupBy()`` method +- Sort the groups by the ``runtime`` field by using the ``orderBy()`` method +- Return ``title`` data from the last document in the grouped result by + specifying it in the ``get()`` method + +.. tip:: + + The ``groupBy()`` method calls the MongoDB ``$group`` aggregation operator + and ``$last`` accumulator operator. To learn more about these operators, see + :manual:`$group (aggregation) ` + in the {+server-docs-name+}. + +.. io-code-block:: + :copyable: true + + .. input:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query groupBy + :end-before: end query groupBy + + .. output:: + :language: json + :visible: false + + [ + ... + { + "_id": { "runtime": 64 }, + "runtime": 64, + "title": "Stitch! The Movie" + }, + { + "_id": { "runtime": 67 }, + "runtime": 67, + "title": "Bartok the Magnificent" + }, + { + "_id": { "runtime":68 }, + "runtime": 68, + "title": "Mickey's Twice Upon a Christmas" + }, + ... + ] + +.. _laravel-query-builder-aggregation-count: + +Number of Results Example +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following example shows how to use the ``count()`` +query builder method to return the number of documents +contained in the ``movies`` collection: + +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin aggregation count + :end-before: end aggregation count + +.. _laravel-query-builder-aggregation-max: + +Maximum Value of a Field Example +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following example shows how to use the ``max()`` +query builder method to return the highest numerical +value of the ``runtime`` field from the entire +``movies`` collection: + +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin aggregation max + :end-before: end aggregation max + +.. _laravel-query-builder-aggregation-min: + +Minimum Value of a Field Example +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following example shows how to use the ``min()`` +query builder method to return the lowest numerical +value of the ``year`` field from the entire ``movies`` +collection: + +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin aggregation min + :end-before: end aggregation min + +.. _laravel-query-builder-aggregation-avg: + +Average Value of a Field Example +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following example shows how to use the ``avg()`` +query builder method to return the numerical average, or +arithmetic mean, of the ``imdb.rating`` values from +the entire ``movies`` collection. + +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin aggregation avg + :end-before: end aggregation avg + +.. _laravel-query-builder-aggregation-sum: + +Summed Value of a Field Example +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following example shows how to use the ``sum()`` +query builder method to return the numerical total of +the ``imdb.votes`` values from the entire ``movies`` +collection: + + +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin aggregation sum + :end-before: end aggregation sum + +.. _laravel-query-builder-aggregate-matched: + +Aggregate Matched Results Example +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following example shows how to aggregate data +from results that match a query. The query matches all +movies after the year ``2000`` and computes the average +value of ``imdb.rating`` of those matches by using the +``avg()`` method: -.. code-block:: php +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin aggregation with filter + :end-before: end aggregation with filter - $users = - Users::groupBy('title') - ->get(['title', 'name']); +.. _laravel-modify-results-query-builder: -**Distinct** +Modify Query Results +-------------------- -Distinct requires a field for which to return the distinct values. +This section includes query builder examples for the +following functions that modify the order and format +of query results: + +- :ref:`Order results by the value of a field ` +- :ref:`Omit a specified number of results ` +- :ref:`Show a subset of fields and array values in the results ` +- :ref:`Paginate the results ` + +.. _laravel-query-builder-orderby: + +Order Results Example +~~~~~~~~~~~~~~~~~~~~~ + +The following example shows how to use the ``orderBy()`` +query builder method to arrange the results that match +the filter specified in the ``title`` field by the +``imdb.rating`` value in descending order: + +.. io-code-block:: + :copyable: true + + .. input:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query orderBy + :end-before: end query orderBy + + .. output:: + :language: json + :visible: false + + [ + { "title": "Back to the Future", "imdb": { "rating":8.5,"votes":636511,"id":88763 }, ... }, + { "title": "Back to the Future Part II", "imdb": { "rating":7.8,"votes":292539,"id":96874 }, ... }, + { "title": "Back to the Future Part III", "imdb": {"rating":7.4,"votes":242390,"id":99088 }, ... }, + ... + ] + +.. _laravel-query-builder-skip: + +Omit a Specified Number of Results Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following example shows how to use the ``skip()`` query builder method to +omit the first four results that match the filter specified in the ``title`` +field, sorted by the ``year`` value in ascending order: + +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query skip + :end-before: end query skip + +.. _laravel-query-builder-project: + +Show a Subset of Fields and Array Values in the Results Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following example shows how to use the ``project()`` +query builder method to match documents that contain an +``imdb.rating`` value higher than ``8.5`` and return +only the following field values: + +- Title of the movie in the ``title`` +- Second through fourth values of the ``cast`` array field, if they exist +- Document ``_id`` field, which is automatically included + +.. io-code-block:: + :copyable: true + + .. input:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query projection + :end-before: end query projection + + .. output:: + :language: json + :visible: false + + [ + { + "_id": { ... }, + "title": "City Lights" + "cast": [ + "Florence Lee", + "Harry Myers", + "Al Ernest Garcia" + ], + }, + { + "_id": { ... }, + "title": "Modern Times", + "cast": [ + "Paulette Goddard", + "Henry Bergman", + "Tiny Sandford" + ] + }, + { + "_id": { ... }, + "title": "Casablanca" + "cast": [ + "Ingrid Bergman", + "Paul Henreid", + "Claude Rains" + ], + }, + ... + ] + +.. _laravel-query-builder-paginate: + +Paginate the Results Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. code-block:: php +The following example shows how to use the ``paginate()`` query builder method +to divide the entire ``movie`` collection into discrete result sets of 15 +documents. The example also includes a sort order to arrange the results by +the ``imdb.votes`` field in descending order and a projection that includes +only specific fields in the results. - $users = User::distinct()->get(['name']); +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query projection with pagination + :end-before: end query projection with pagination - // Equivalent to: - $users = User::distinct('name')->get(); +To learn more about pagination, see +`Paginating Query Builder Results `__ +in the Laravel documentation. -Distinct can be combined with **where**: +.. _laravel-mongodb-read-query-builder: -.. code-block:: php +Retrieve Data by Using MongoDB Operations +----------------------------------------- - $users = - User::where('active', true) - ->distinct('name') - ->get(); +This section includes query builder examples that show how +to use the following MongoDB-specific query operations: -**Like** +- :ref:`Match documents that contain a field ` +- :ref:`Match documents that contain all specified fields ` +- :ref:`Match documents that contain a specific number of elements in an array ` +- :ref:`Match documents that contain a particular data type in a field ` +- :ref:`Match documents that contain a computed modulo value ` +- :ref:`Match documents that match a regular expression ` +- :ref:`Run MongoDB Query API operations ` +- :ref:`Match documents that contain array elements ` +- :ref:`Specify a cursor timeout ` +- :ref:`Match locations by using geospatial searches ` -.. code-block:: php +.. _laravel-query-builder-exists: - $spamComments = Comment::where('body', 'like', '%spam%')->get(); +Contains a Field Example +~~~~~~~~~~~~~~~~~~~~~~~~ -.. _laravel-query-builder-aggregates: +The following example shows how to use the ``exists()`` +query builder method to match documents that contain the +field ``random_review``: -**Aggregation** +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query exists + :end-before: end query exists -**Aggregations are only available for MongoDB versions greater than 2.2.x** +To learn more about this query operator, see +:manual:`$exists ` +in the {+server-docs-name+}. -.. code-block:: php +.. _laravel-query-builder-all: - $total = Product::count(); - $price = Product::max('price'); - $price = Product::min('price'); - $price = Product::avg('price'); - $total = Product::sum('price'); - -Aggregations can be combined with **where**: +Contains All Fields Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. code-block:: php +The following example shows how to use the ``all`` query +operator with the ``where()`` query builder method to match +documents that contain all the specified fields: - $sold = Orders::where('sold', true)->sum('price'); +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query all + :end-before: end query all -Aggregations can be also used on sub-documents: +To learn more about this query operator, see +:manual:`$all ` +in the {+server-docs-name+}. -.. code-block:: php +.. _laravel-query-builder-size: - $total = Order::max('suborder.price'); +Match Array Size Example +~~~~~~~~~~~~~~~~~~~~~~~~ -.. note:: +The following example shows how to pass the ``size`` +query operator with the ``where()`` query builder +method to match documents that contain a ``directors`` +field that contains an array of exactly five elements: - This aggregation only works with single sub-documents (like ``EmbedsOne``) - not subdocument arrays (like ``EmbedsMany``). +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query size + :end-before: end query size -**Incrementing/Decrementing the value of a column** +To learn more about this query operator, see +:manual:`$size ` +in the {+server-docs-name+}. -Perform increments or decrements (default 1) on specified attributes: +.. _laravel-query-builder-type: -.. code-block:: php +Match Data Type Example +~~~~~~~~~~~~~~~~~~~~~~~ - Cat::where('name', 'Kitty')->increment('age'); +The following example shows how to pass the ``type`` +query operator with the ``where()`` query builder +method to match documents that contain a type ``4`` value, +which corresponds to an array data type, in the +``released`` field. - Car::where('name', 'Toyota')->decrement('weight', 50); +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query type + :end-before: end query type -The number of updated objects is returned: +To learn more about the type codes and query operator, see +:manual:`$type ` +in the {+server-docs-name+}. -.. code-block:: php +.. _laravel-query-builder-mod: - $count = User::increment('age'); +Match a Value Computed with Modulo Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You may also specify more columns to update: +The following example shows how to pass the ``mod`` +query operator with the ``where()`` query builder +method to match documents by using the expression +``year % 2 == 0``, which matches even values for +the ``year`` field: -.. code-block:: php +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query modulo + :end-before: end query modulo - Cat::where('age', 3) - ->increment('age', 1, ['group' => 'Kitty Club']); +To learn more about this query operator, see +:manual:`$mod ` +in the {+server-docs-name+}. - Car::where('weight', 300) - ->decrement('weight', 100, ['latest_change' => 'carbon fiber']); +.. _laravel-query-builder-regex: -MongoDB-specific operators +Match a Regular Expression ~~~~~~~~~~~~~~~~~~~~~~~~~~ -In addition to the Laravel Eloquent operators, all available MongoDB query -operators can be used with ``where``: +The following example shows how to pass the ``REGEX`` +query operator with the ``where()`` query builder +method to match documents that contain a ``title`` +field that matches the specified regular expression: -.. code-block:: php - - User::where($fieldName, $operator, $value)->get(); +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query whereRegex + :end-before: end query whereRegex -It generates the following MongoDB filter: +To learn more about regular expression queries in MongoDB, see +:manual:`$regex ` +in the {+server-docs-name+}. -.. code-block:: ts +.. _laravel-query-builder-whereRaw: - { $fieldName: { $operator: $value } } +Run MongoDB Query API Operations Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**Exists** +The following example shows how to use the ``whereRaw()`` +query builder method to run a query operation written by +using the MongoDB Query API syntax: -Matches documents that have the specified field. - -.. code-block:: php +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query raw + :end-before: end query raw - User::where('age', 'exists', true)->get(); +The following code shows the equivalent MongoDB Query API syntax: -**All** - -Matches arrays that contain all elements specified in the query. +.. code-block:: -.. code-block:: php + db.movies.find({ + "imdb.votes": { $gte: 1000 }, + $or: [{ + imdb.rating: { $gt: 7 }, + directors: { $in: [ "Yasujiro Ozu", "Sofia Coppola", "Federico Fellini" ] } + }]}); - User::where('roles', 'all', ['moderator', 'author'])->get(); +To learn more about the MongoDB Query API, see +:manual:`MongoDB Query API ` in the {+server-docs-name+}. -**Size** +.. _laravel-query-builder-elemMatch: -Selects documents if the array field is a specified size. +Match Array Elements Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. code-block:: php +The following example shows how to pass the ``elemMatch`` +query operator with the ``where()`` query builder +method to match documents that contain an array element +that matches at least one of the conditions in the +specified query: - Post::where('tags', 'size', 3)->get(); +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query elemMatch + :end-before: end query elemMatch -**Regex** +To learn more about regular expression queries in MongoDB, see +the :manual:`$elemMatch operator ` +in the {+server-docs-name+}. -Selects documents where values match a specified regular expression. +.. _laravel-query-builder-cursor-timeout: -.. code-block:: php +Specify Cursor Timeout Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - use MongoDB\BSON\Regex; +The following example shows how to use the ``timeout()`` method +to specify a maximum duration to wait for cursor operations to complete. - User::where('name', 'regex', new Regex('.*doe', 'i'))->get(); +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query cursor timeout + :end-before: end query cursor timeout .. note:: - You can also use the Laravel regexp operations. These will automatically - convert your regular expression string to a ``MongoDB\BSON\Regex`` object. - -.. code-block:: php - - User::where('name', 'regexp', '/.*doe/i')->get(); - -The inverse of regexp: - -.. code-block:: php - - User::where('name', 'not regexp', '/.*doe/i')->get(); + This setting specifies a ``maxTimeMS`` value in seconds instead of + milliseconds. To learn more about the ``maxTimeMS`` value, see + `MongoDB\Collection::find() `__ + in the PHP Library documentation. -**ElemMatch** +.. _laravel-query-builder-geospatial: -The :manual:`$elemMatch ` operator -matches documents that contain an array field with at least one element that -matches all the specified query criteria. +Match Locations by Using Geospatial Operations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The following query matches only those documents where the results array -contains at least one element that is both greater than or equal to 80 and -is less than 85: +The examples in this section show the query builder syntax you +can use to perform geospatial queries on GeoJSON or coordinate +pair data to retrieve the following types of locations: -.. code-block:: php +- :ref:`Near a position ` +- :ref:`Within a the boundary of a GeoJSON object ` +- :ref:`Intersecting a GeoJSON object ` +- :ref:`Proximity data for nearby matches ` - User::where('results', 'elemMatch', ['gte' => 80, 'lt' => 85])->get(); +.. important:: -A closure can be used to create more complex sub-queries. + To perform GeoJSON queries in MongoDB, you must create either ``2d`` or + ``2dsphere`` index on the collection. To learn how to create geospatial + indexes, see the :ref:`laravel-eloquent-geospatial-index` section in the + Schema Builder guide. -The following query matches only those documents where the results array -contains at least one element with both product equal to "xyz" and score -greater than or equal to 8: +To learn more about GeoJSON objects that MongoDB supports, +see :manual:`GeoJSON Objects ` +in the {+server-docs-name+}. -.. code-block:: php +.. _laravel-query-builder-geospatial-near: - User::where('results', 'elemMatch', function (Builder $builder) { - $builder - ->where('product', 'xyz') - ->andWhere('score', '>', 50); - })->get(); +Near a Position Example +~~~~~~~~~~~~~~~~~~~~~~~ -**Type** +The following example shows how to use the ``near`` query operator +with the ``where()`` query builder method to match documents that +contain a location that is up to ``50`` meters from a GeoJSON Point +object: -Selects documents if a field is of the specified type. For more information -check: :manual:`$type ` in the -MongoDB Server documentation. +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query near + :end-before: end query near -.. code-block:: php +To learn more about this operator, see +:manual:`$near operator ` +in the {+server-docs-name+}. - User::where('age', 'type', 2)->get(); +.. _laravel-query-builder-geospatial-geoWithin: -**Mod** +Within an Area Example +~~~~~~~~~~~~~~~~~~~~~~ -Performs a modulo operation on the value of a field and selects documents with -a specified result. +The following example shows how to use the ``geoWithin`` +query operator with the ``where()`` +query builder method to match documents that contain a +location within the bounds of the specified ``Polygon`` +GeoJSON object: -.. code-block:: php +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query geoWithin + :end-before: end query geoWithin - User::where('age', 'mod', [10, 0])->get(); +.. _laravel-query-builder-geospatial-geoIntersects: -MongoDB-specific Geo operations +Intersecting a Geometry Example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**Near** - -.. code-block:: php - - $bars = Bar::where('location', 'near', [ - '$geometry' => [ - 'type' => 'Point', - 'coordinates' => [ - -0.1367563, // longitude - 51.5100913, // latitude - ], - ], - '$maxDistance' => 50, - ])->get(); - -**GeoWithin** - -.. code-block:: php - - $bars = Bar::where('location', 'geoWithin', [ - '$geometry' => [ - 'type' => 'Polygon', - 'coordinates' => [ - [ - [-0.1450383, 51.5069158], - [-0.1367563, 51.5100913], - [-0.1270247, 51.5013233], - [-0.1450383, 51.5069158], - ], - ], - ], - ])->get(); - -**GeoIntersects** - -.. code-block:: php - - $bars = Bar::where('location', 'geoIntersects', [ - '$geometry' => [ - 'type' => 'LineString', - 'coordinates' => [ - [-0.144044, 51.515215], - [-0.129545, 51.507864], - ], - ], - ])->get(); - -**GeoNear** - -You can make a ``geoNear`` query on MongoDB. -You can omit specifying the automatic fields on the model. -The returned instance is a collection, so you can call the `Collection `__ operations. -Make sure that your model has a ``location`` field, and a -`2ndSphereIndex `__. -The data in the ``location`` field must be saved as `GeoJSON `__. -The ``location`` points must be saved as `WGS84 `__ -reference system for geometry calculation. That means that you must -save ``longitude and latitude``, in that order specifically, and to find near -with calculated distance, you ``must do the same way``. +The following example shows how to use the ``geoInstersects`` +query operator with the ``where()`` query builder method to +match documents that contain a location that intersects with +the specified ``LineString`` GeoJSON object: -.. code-block:: +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query geoIntersects + :end-before: end query geoIntersects - Bar::find("63a0cd574d08564f330ceae2")->update( - [ - 'location' => [ - 'type' => 'Point', - 'coordinates' => [ - -0.1367563, - 51.5100913 - ] - ] - ] - ); - $bars = Bar::raw(function ($collection) { - return $collection->aggregate([ - [ - '$geoNear' => [ - "near" => [ "type" => "Point", "coordinates" => [-0.132239, 51.511874] ], - "distanceField" => "dist.calculated", - "minDistance" => 0, - "maxDistance" => 6000, - "includeLocs" => "dist.location", - "spherical" => true, - ] - ] - ]); - }); - -Inserts, updates and deletes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. _laravel-query-builder-geospatial-geoNear: -Inserting, updating and deleting records works just like the original Eloquent. -Please check `Laravel Docs' Eloquent section `__. +Proximity Data for Nearby Matches Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Here, only the MongoDB-specific operations are specified. +The following example shows how to use the ``geoNear`` aggregation operator +with the ``raw()`` query builder method to perform an aggregation that returns +metadata, such as proximity information for each match: -MongoDB specific operations -~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin query geoNear + :end-before: end query geoNear -**Raw Expressions** +To learn more about this aggregation operator, see +:manual:`$geoNear operator ` +in the {+server-docs-name+}. -These expressions will be injected directly into the query. +.. _laravel-mongodb-write-query-builder: -.. code-block:: php +Write Data by Using MongoDB Write Operations +-------------------------------------------- - User::whereRaw([ - 'age' => ['$gt' => 30, '$lt' => 40], - ])->get(); +This section includes query builder examples that show how to use the +following MongoDB-specific write operations: - User::whereRaw([ - '$where' => '/.*123.*/.test(this.field)', - ])->get(); +- :ref:`Upsert a document ` +- :ref:`Increment a numerical value ` +- :ref:`Decrement a numerical value ` +- :ref:`Add an array element ` +- :ref:`Remove a value from an array ` +- :ref:`Remove a field from a document ` - User::whereRaw([ - '$where' => '/.*123.*/.test(this["hyphenated-field"])', - ])->get(); +.. _laravel-mongodb-query-builder-upsert: -You can also perform raw expressions on the internal MongoCollection object. -If this is executed on the model class, it will return a collection of models. +Upsert a Document Example +~~~~~~~~~~~~~~~~~~~~~~~~~ -If this is executed on the query builder, it will return the original response. +The following example shows how to use the ``update()`` query builder method +and ``upsert`` option to update the matching document or insert one with the +specified data if it does not exist. When you set the ``upsert`` option to +``true`` and the document does not exist, the command inserts both the data +and the ``title`` field and value specified in the ``where()`` query operation: -**Cursor timeout** +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin upsert + :end-before: end upsert -To prevent ``MongoCursorTimeout`` exceptions, you can manually set a timeout -value that will be applied to the cursor: +The ``update()`` query builder method returns the number of documents that the +operation updated or inserted. -.. code-block:: php +.. _laravel-mongodb-query-builder-increment: - DB::collection('users')->timeout(-1)->get(); +Increment a Numerical Value Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**Upsert** +The following example shows how to use the ``increment()`` +query builder method to add ``3000`` to the value of +the ``imdb.votes`` field in the matched document: -Update or insert a document. Other options for the update method can be -passed directly to the native update method. +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin increment + :end-before: end increment -.. code-block:: php +The ``increment()`` query builder method returns the number of documents that the +operation updated. - // Query Builder - DB::collection('users') - ->where('name', 'John') - ->update($data, ['upsert' => true]); +.. _laravel-mongodb-query-builder-decrement: - // Eloquent - $user->update($data, ['upsert' => true]); +Decrement a Numerical Value Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**Projections** +The following example shows how to use the ``decrement()`` query builder +method to subtract ``0.2`` from the value of the ``imdb.rating`` field in the +matched document: -You can apply projections to your queries using the ``project`` method. +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin decrement + :end-before: end decrement -.. code-block:: php +The ``decrement()`` query builder method returns the number of documents that the +operation updated. - DB::collection('items') - ->project(['tags' => ['$slice' => 1]]) - ->get(); +.. _laravel-mongodb-query-builder-push: - DB::collection('items') - ->project(['tags' => ['$slice' => [3, 7]]]) - ->get(); - -**Projections with Pagination** - -.. code-block:: php - - $limit = 25; - $projections = ['id', 'name']; - - DB::collection('items') - ->paginate($limit, $projections); - -**Push** - -Add items to an array. - -.. code-block:: php - - DB::collection('users') - ->where('name', 'John') - ->push('items', 'boots'); - - $user->push('items', 'boots'); - -.. code-block:: php - - DB::collection('users') - ->where('name', 'John') - ->push('messages', [ - 'from' => 'Jane Doe', - 'message' => 'Hi John', - ]); - - $user->push('messages', [ - 'from' => 'Jane Doe', - 'message' => 'Hi John', - ]); - -If you **DON'T** want duplicate items, set the third parameter to ``true``: - -.. code-block:: php - - DB::collection('users') - ->where('name', 'John') - ->push('items', 'boots', true); - - $user->push('items', 'boots', true); - -**Pull** - -Remove an item from an array. - -.. code-block:: php - - DB::collection('users') - ->where('name', 'John') - ->pull('items', 'boots'); +Add an Array Element Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - $user->pull('items', 'boots'); +The following example shows how to use the ``push()`` query builder method to +add ``"Gary Cole"`` to the ``cast`` array field in the matched document: -.. code-block:: php +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin push + :end-before: end push - DB::collection('users') - ->where('name', 'John') - ->pull('messages', [ - 'from' => 'Jane Doe', - 'message' => 'Hi John', - ]); +The ``push()`` query builder method returns the number of documents that the +operation updated. - $user->pull('messages', [ - 'from' => 'Jane Doe', - 'message' => 'Hi John', - ]); +.. _laravel-mongodb-query-builder-pull: -**Unset** +Remove an Array Element Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Remove one or more fields from a document. +The following example shows how to use the ``pull()`` query builder method +to remove the ``"Adventure"`` value from the ``genres`` field from the document +matched by the query: -.. code-block:: php +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin pull + :end-before: end pull - DB::collection('users') - ->where('name', 'John') - ->unset('note'); +The ``pull()`` query builder method returns the number of documents that the +operation updated. - $user->unset('note'); +.. _laravel-mongodb-query-builder-unset: - $user->save(); +Remove a Field Example +~~~~~~~~~~~~~~~~~~~~~~ -Using the native ``unset`` on models will work as well: +The following example shows how to use the ``unset()`` query builder method +to remove the ``tomatoes.viewer`` field and value from the document matched +by the query: -.. code-block:: php +.. literalinclude:: /includes/query-builder/QueryBuilderTest.php + :language: php + :dedent: + :start-after: begin unset + :end-before: end unset - unset($user['note']); - unset($user->node); +The ``unset()`` query builder method returns the number of documents that the +operation updated. diff --git a/docs/retrieve.txt b/docs/retrieve.txt index 1665291e8..a295c0bb8 100644 --- a/docs/retrieve.txt +++ b/docs/retrieve.txt @@ -43,7 +43,7 @@ sample data and creating the following files in your Laravel web application: - ``browse_movies.blade.php`` file, which contains HTML code to display the results of database operations -The following sections describe how to edit the files in your Laravel application to run +The following sections describe how to edit the files in your Laravel application to run the find operation code examples and view the expected output. .. _laravel-retrieve-matching: @@ -51,41 +51,37 @@ the find operation code examples and view the expected output. 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 use Laravel's Eloquent object-relational mapper (ORM) to create models +that represent MongoDB collections and chain methods on them to specify +query criteria. -You can use one of the following ``where()`` method calls to build a query: - -- ``where('', )``: builds a query that matches documents in which the - target field has the exact specified value +To retrieve documents that match a set of criteria, pass a query filter to the +``where()`` method. -- ``where('', '', )``: builds a query that matches - documents in which the target field's value meets the comparison criteria +A query filter specifies field value requirements and instructs the find +operation to return only documents that meet these requirements. -After building your query with the ``where()`` method, use the ``get()`` method to -retrieve the query results. +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. -To apply multiple sets of criteria to the find operation, you can chain a series -of ``where()`` methods together. - -.. tip:: +You can use one of the following ``where()`` method calls to build a query: - To learn more about other query methods in {+odm-short+}, see the :ref:`laravel-query-builder` - page. +- ``where('', )`` builds a query that matches documents in + which the target field has the exact specified value -.. _laravel-retrieve-eloquent: +- ``where('', '', )`` builds a query + that matches documents in which the target field's value meets the comparison + criteria -Use Eloquent Models to Retrieve Documents -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +To apply multiple sets of criteria to the find operation, you can chain a series +of ``where()`` methods together. -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. +After building your query with the ``where()`` method, chain the ``get()`` +method to retrieve the query results. -This example calls two ``where()`` methods on the ``Movie`` Eloquent model to retrieve -documents that meet the following criteria: +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`` @@ -122,7 +118,7 @@ documents that meet the following criteria: $movies = Movie::where('year', 2010) ->where('imdb.rating', '>', 8.5) ->get(); - + return view('browse_movies', [ 'movies' => $movies ]); @@ -149,132 +145,8 @@ documents that meet the following criteria: 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. - -This example uses Laravel's query builder to retrieve documents in which the value -of the ``imdb.votes`` nested field is ``350``. - -.. tabs:: - - .. tab:: Query Syntax - :tabid: query-syntax - - Use the following syntax to specify the query: - - .. code-block:: php - - $movies = DB::connection('mongodb') - ->collection('movies') - ->where('imdb.votes', 350) - ->get(); - - .. tab:: Controller Method - :tabid: controller - - To see the query results in the ``browse_movies`` view, edit the ``show()`` function - in the ``MovieController.php`` file to resemble the following code: - - .. io-code-block:: - :copyable: true - - .. input:: - :language: php - - class MovieController - { - public function show() - { - $movies = DB::connection('mongodb') - ->collection('movies') - ->where('imdb.votes', 350) - ->get(); - - return view('browse_movies', [ - 'movies' => $movies - ]); - } - } - - .. output:: - :language: none - :visible: false - - Title: Murder in New Hampshire: The Pamela Wojas Smart Story - Year: 1991 - Runtime: 100 - IMDB Rating: 5.9 - IMDB Votes: 350 - Plot: Pamela Smart knows exactly what she wants and is willing to do - anything to get it. She is fed up with teaching, and her marriage offers - little excitement. Looking for a way out she applies ... - - Title: Ah Fu - Year: 2000 - Runtime: 105 - IMDB Rating: 6.6 - IMDB Votes: 350 - Plot: After a 13-year imprisonment in Hong Kong, a kickboxer challenges the - current champion in order to restore his honor. - - Title: Bandage - Year: 2010 - Runtime: 119 - IMDB Rating: 7 - IMDB Votes: 350 - Plot: Four boys have their friendship and musical talents tested in the ever - changing worlds of the music industry and real life in 1990s Japan. - - Title: Great Migrations - Year: 2010 - Runtime: 45 - IMDB Rating: 8.2 - IMDB Votes: 350 - Plot: Great Migrations takes viewers on the epic journeys animals undertake to - ensure the survival of their species. - - Then, make the following changes to your Laravel Quick Start application: - - - Import the ``DB`` facade into your ``MovieController.php`` file by adding the - ``use Illuminate\Support\Facades\DB`` use statement - - Replace the contents of your ``browse_movies.blade.php`` file with the following code: - - .. code-block:: php - - - - - Browse Movies - - -

Movies

- - @forelse ($movies as $movie) -

- Title: {{ $movie['title'] }}
- Year: {{ $movie['year'] }}
- Runtime: {{ $movie['runtime'] }}
- IMDB Rating: {{ $movie['imdb']['rating'] }}
- IMDB Votes: {{ $movie['imdb']['votes'] }}
- Plot: {{ $movie['plot'] }}
-

- @empty -

No results

- @endforelse - - - - - .. note:: - - Since the Laravel query builder returns data as an array rather than as instances of the Eloquent model class, - the view accesses the fields by using the array syntax instead of the ``->`` object operator. +To learn how to query by using the Laravel query builder instead of the +Eloquent ORM, see the :ref:`laravel-query-builder` page. .. _laravel-retrieve-all: @@ -295,10 +167,10 @@ Use the following syntax to run a find operation that matches all documents: .. 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. - - To avoid this issue, specify a document limit by using the ``take()`` method. For + Retrieving and displaying all documents in this collection might cause your web + application to time out. + + To avoid this issue, specify a document limit by using the ``take()`` method. For more information about ``take()``, see the :ref:`laravel-modify-find` section of this guide. @@ -462,7 +334,7 @@ field. IMDB Votes: 620 Plot: A documentary of black art. -.. tip:: +.. tip:: To learn more about sorting, see the following resources: