diff --git a/docs/fundamentals/read-operations.txt b/docs/fundamentals/read-operations.txt index 44eba023f..0201cb782 100644 --- a/docs/fundamentals/read-operations.txt +++ b/docs/fundamentals/read-operations.txt @@ -29,6 +29,7 @@ This guide shows you how to perform the following tasks: - :ref:`laravel-retrieve-matching` - :ref:`laravel-retrieve-all` +- :ref:`laravel-retrieve-text-search` - :ref:`Modify Find Operation Behavior ` Before You Get Started @@ -175,6 +176,121 @@ Use the following syntax to run a find operation that matches all documents: more information about ``take()``, see the :ref:`laravel-modify-find` section of this guide. +.. _laravel-retrieve-text-search: + +Search Text Fields +------------------ + +A text search retrieves documents that contain a **term** or a **phrase** in the +text-indexed fields. A term is a sequence of characters that excludes +whitespace characters. A phrase is a sequence of terms with any number +of whitespace characters. + +.. note:: + + Before you can perform a text search, you must create a :manual:`text + index ` on + the text-valued field. To learn more about creating + indexes, see the :ref:`laravel-eloquent-indexes` section of the + Schema Builder guide. + +You can perform a text search by using the :manual:`$text +` operator followed +by the ``$search`` field in your query filter that you pass to the +``where()`` method. The ``$text`` operator performs a text search on the +text-indexed fields. The ``$search`` field specifies the text to search for. + +After building your query with the ``where()`` method, chain the ``get()`` +method to retrieve the query results. + +This example calls the ``where()`` method on the ``Movie`` Eloquent model to +retrieve documents in which the ``plot`` field contains the phrase +``"love story"``. To perform this text search, the collection must have +a text index on the ``plot`` field. + +.. tabs:: + + .. tab:: Query Syntax + :tabid: query-syntax + + Use the following syntax to specify the query: + + .. literalinclude:: /includes/fundamentals/read-operations/ReadOperationsTest.php + :language: php + :dedent: + :start-after: start-text + :end-before: end-text + + .. 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 = Movie::where('$text', ['$search' => '"love story"']) + ->get(); + + return view('browse_movies', [ + 'movies' => $movies + ]); + } + } + + .. output:: + :language: none + :visible: false + + Title: Cafè de Flore + Year: 2011 + Runtime: 120 + IMDB Rating: 7.4 + IMDB Votes: 9663 + Plot: A love story between a man and woman ... + + Title: Paheli + Year: 2005 + Runtime: 140 + IMDB Rating: 6.7 + IMDB Votes: 8909 + Plot: A folk tale - supernatural love story about a ghost ... + + Title: Por un puèado de besos + Year: 2014 + Runtime: 98 + IMDB Rating: 6.1 + IMDB Votes: 223 + Plot: A girl. A boy. A love story ... + + ... + +A text search assigns a numerical :manual:`text score ` to indicate how closely +each result matches the string in your query filter. You can sort the +results by relevance by using the ``orderBy()`` method to sort on the +``textScore`` metadata field. You can access this metadata by using the +:manual:`$meta ` operator: + +.. literalinclude:: /includes/fundamentals/read-operations/ReadOperationsTest.php + :language: php + :dedent: + :start-after: start-text-relevance + :end-before: end-text-relevance + :emphasize-lines: 2 + +.. tip:: + + To learn more about the ``orderBy()`` method, see the + :ref:`laravel-sort` section of this guide. + .. _laravel-modify-find: Modify Behavior diff --git a/docs/includes/fundamentals/read-operations/ReadOperationsTest.php b/docs/includes/fundamentals/read-operations/ReadOperationsTest.php index b415c29e3..a2080ec8f 100644 --- a/docs/includes/fundamentals/read-operations/ReadOperationsTest.php +++ b/docs/includes/fundamentals/read-operations/ReadOperationsTest.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers; use App\Models\Movie; +use Illuminate\Support\Facades\DB; use MongoDB\Laravel\Tests\TestCase; class ReadOperationsTest extends TestCase @@ -15,7 +16,10 @@ protected function setUp(): void parent::setUp(); - Movie::truncate(); + $moviesCollection = DB::connection('mongodb')->getCollection('movies'); + $moviesCollection->drop(); + $moviesCollection->createIndex(['plot' => 'text']); + Movie::insert([ ['year' => 2010, 'imdb' => ['rating' => 9]], ['year' => 2010, 'imdb' => ['rating' => 9.5]], @@ -26,6 +30,9 @@ protected function setUp(): void ['year' => 1999, 'countries' => ['Indonesia'], 'title' => 'Title 4'], ['year' => 1999, 'countries' => ['Canada'], 'title' => 'Title 5'], ['year' => 1999, 'runtime' => 30], + ['title' => 'movie_a', 'plot' => 'this is a love story'], + ['title' => 'movie_b', 'plot' => 'love is a long story'], + ['title' => 'movie_c', 'plot' => 'went on a trip'], ]); } @@ -94,4 +101,36 @@ public function testFirst(): void $this->assertNotNull($movie); $this->assertInstanceOf(Movie::class, $movie); } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testText(): void + { + // start-text + $movies = Movie::where('$text', ['$search' => '"love story"']) + ->get(); + // end-text + + $this->assertNotNull($movies); + $this->assertCount(1, $movies); + } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testTextRelevance(): void + { + // start-text-relevance + $movies = Movie::where('$text', ['$search' => '"love story"']) + ->orderBy('score', ['$meta' => 'textScore']) + ->get(); + // end-text-relevance + + $this->assertNotNull($movies); + $this->assertCount(1, $movies); + $this->assertEquals('this is a love story', $movies[0]->plot); + } }