From 2f9b58a4f646e571a71976cfe43c992c4a826a21 Mon Sep 17 00:00:00 2001 From: rustagir Date: Fri, 19 Apr 2024 13:31:35 -0400 Subject: [PATCH 1/7] DOCSP-35959: search text --- docs/fundamentals/read-operations.txt | 117 ++++++++++++++++++ .../read-operations/ReadOperationsTest.php | 35 ++++++ 2 files changed, 152 insertions(+) diff --git a/docs/fundamentals/read-operations.txt b/docs/fundamentals/read-operations.txt index 44eba023f..cd8e4b1cc 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,122 @@ 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 +------------------ + +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. + +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. + +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"``: + +.. 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 ... + +.. note:: + + To specify a phrase as the text search criteria, you must include it + with escaped quotes in the query filter. + +A text search assigns a numerical 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: + +.. 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..37145426e 100644 --- a/docs/includes/fundamentals/read-operations/ReadOperationsTest.php +++ b/docs/includes/fundamentals/read-operations/ReadOperationsTest.php @@ -26,6 +26,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', 'fullplot' => 'this is a love story'], + ['title' => 'movie_b', 'fullplot' => 'love is a long story'], + ['title' => 'movie_c', 'fullplot' => 'went on a trip'], ]); } @@ -94,4 +97,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(2, $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(2, $movies); + } + } From fee1259897dbc55f983628e8c1d8570a4e7db17c Mon Sep 17 00:00:00 2001 From: rustagir Date: Fri, 19 Apr 2024 13:40:00 -0400 Subject: [PATCH 2/7] code fixes --- docs/fundamentals/read-operations.txt | 2 ++ .../read-operations/ReadOperationsTest.php | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/fundamentals/read-operations.txt b/docs/fundamentals/read-operations.txt index cd8e4b1cc..2dc72c3a1 100644 --- a/docs/fundamentals/read-operations.txt +++ b/docs/fundamentals/read-operations.txt @@ -269,6 +269,8 @@ retrieve documents in which the ``plot`` field contains the phrase IMDB Rating: 6.1 IMDB Votes: 223 Plot: A girl. A boy. A love story ... + + ... .. note:: diff --git a/docs/includes/fundamentals/read-operations/ReadOperationsTest.php b/docs/includes/fundamentals/read-operations/ReadOperationsTest.php index 37145426e..1077694fe 100644 --- a/docs/includes/fundamentals/read-operations/ReadOperationsTest.php +++ b/docs/includes/fundamentals/read-operations/ReadOperationsTest.php @@ -26,9 +26,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', 'fullplot' => 'this is a love story'], - ['title' => 'movie_b', 'fullplot' => 'love is a long story'], - ['title' => 'movie_c', 'fullplot' => 'went on a trip'], + ['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'], ]); } @@ -119,6 +119,11 @@ public function testText(): void */ public function testTextRelevance(): void { + + $collection = MongoDB::connection('mongodb')->collection('movies'); + $index = ['plot' => 'text']; + $collection->createIndex($index); + // start-text-relevance $movies = Movie::where('$text', ['$search' => "\"" . 'love story' . "\""]) ->orderBy('score', ['$meta' => 'textScore']) From a5f8a64ca2236daacb26f40430879342b82db9b2 Mon Sep 17 00:00:00 2001 From: rustagir Date: Fri, 19 Apr 2024 15:04:27 -0400 Subject: [PATCH 3/7] JM and CC PR fixes 1 --- docs/fundamentals/read-operations.txt | 25 ++++++++----------- .../read-operations/ReadOperationsTest.php | 4 +-- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/docs/fundamentals/read-operations.txt b/docs/fundamentals/read-operations.txt index 2dc72c3a1..1abae2800 100644 --- a/docs/fundamentals/read-operations.txt +++ b/docs/fundamentals/read-operations.txt @@ -181,12 +181,6 @@ Use the following syntax to run a find operation that matches all documents: Search Text Fields ------------------ -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. - 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 @@ -200,12 +194,19 @@ of whitespace characters. 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"``: +``"love story"``. To perform this text search, the collection must have +a text index on the ``plot`` field. .. tabs:: @@ -271,16 +272,12 @@ retrieve documents in which the ``plot`` field contains the phrase Plot: A girl. A boy. A love story ... ... - -.. note:: - - To specify a phrase as the text search criteria, you must include it - with escaped quotes in the query filter. -A text search assigns a numerical text score to indicate how closely +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: +``textScore`` metadata field. You can access this metadata by using the +:manual:`$meta ` operator: .. literalinclude:: /includes/fundamentals/read-operations/ReadOperationsTest.php :language: php diff --git a/docs/includes/fundamentals/read-operations/ReadOperationsTest.php b/docs/includes/fundamentals/read-operations/ReadOperationsTest.php index 1077694fe..430c2777b 100644 --- a/docs/includes/fundamentals/read-operations/ReadOperationsTest.php +++ b/docs/includes/fundamentals/read-operations/ReadOperationsTest.php @@ -105,7 +105,7 @@ public function testFirst(): void public function testText(): void { // start-text - $movies = Movie::where('$text', ['$search' => "\"" . 'love story' . "\""]) + $movies = Movie::where('$text', ['$search' => '"love story"']) ->get(); // end-text @@ -125,7 +125,7 @@ public function testTextRelevance(): void $collection->createIndex($index); // start-text-relevance - $movies = Movie::where('$text', ['$search' => "\"" . 'love story' . "\""]) + $movies = Movie::where('$text', ['$search' => '"love story"']) ->orderBy('score', ['$meta' => 'textScore']) ->get(); // end-text-relevance From ea79bd00b1dd03e7d80963ddc2b17d1a7da19366 Mon Sep 17 00:00:00 2001 From: rustagir Date: Fri, 19 Apr 2024 15:06:39 -0400 Subject: [PATCH 4/7] fix controller code --- docs/fundamentals/read-operations.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fundamentals/read-operations.txt b/docs/fundamentals/read-operations.txt index 1abae2800..0201cb782 100644 --- a/docs/fundamentals/read-operations.txt +++ b/docs/fundamentals/read-operations.txt @@ -237,7 +237,7 @@ a text index on the ``plot`` field. { public function show() { - $movies = Movie::where('$text', ['$search' => "\"" . 'love story' . "\""]) + $movies = Movie::where('$text', ['$search' => '"love story"']) ->get(); return view('browse_movies', [ From cd6d025a32d28dabef4844eefb41deca990ab04d Mon Sep 17 00:00:00 2001 From: rustagir Date: Fri, 19 Apr 2024 15:08:48 -0400 Subject: [PATCH 5/7] move index creation into setup --- .../fundamentals/read-operations/ReadOperationsTest.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/includes/fundamentals/read-operations/ReadOperationsTest.php b/docs/includes/fundamentals/read-operations/ReadOperationsTest.php index 430c2777b..72bf25cf9 100644 --- a/docs/includes/fundamentals/read-operations/ReadOperationsTest.php +++ b/docs/includes/fundamentals/read-operations/ReadOperationsTest.php @@ -30,6 +30,10 @@ protected function setUp(): void ['title' => 'movie_b', 'plot' => 'love is a long story'], ['title' => 'movie_c', 'plot' => 'went on a trip'], ]); + + $collection = MongoDB::connection('mongodb')->collection('movies'); + $index = ['plot' => 'text']; + $collection->createIndex($index); } /** @@ -119,11 +123,6 @@ public function testText(): void */ public function testTextRelevance(): void { - - $collection = MongoDB::connection('mongodb')->collection('movies'); - $index = ['plot' => 'text']; - $collection->createIndex($index); - // start-text-relevance $movies = Movie::where('$text', ['$search' => '"love story"']) ->orderBy('score', ['$meta' => 'textScore']) From 802f50eb42639e7a7f6b73f5e9ecf1c6cbd52c27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Mon, 22 Apr 2024 17:10:42 +0200 Subject: [PATCH 6/7] Fix index creation in tests --- .../read-operations/ReadOperationsTest.php | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/includes/fundamentals/read-operations/ReadOperationsTest.php b/docs/includes/fundamentals/read-operations/ReadOperationsTest.php index 72bf25cf9..6a453781f 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,14 +30,10 @@ 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_a', 'plot' => 'this is a love story'], ['title' => 'movie_c', 'plot' => 'went on a trip'], ]); - - $collection = MongoDB::connection('mongodb')->collection('movies'); - $index = ['plot' => 'text']; - $collection->createIndex($index); } /** @@ -109,7 +109,7 @@ public function testFirst(): void public function testText(): void { // start-text - $movies = Movie::where('$text', ['$search' => '"love story"']) + $movies = Movie::where('$text', ['$search' => 'love story']) ->get(); // end-text @@ -124,13 +124,13 @@ public function testText(): void public function testTextRelevance(): void { // start-text-relevance - $movies = Movie::where('$text', ['$search' => '"love story"']) - ->orderBy('score', ['$meta' => 'textScore']) + $movies = Movie::where('$text', ['$search' => 'love story']) + ->orderBy('score', ['$meta' => 'textScore']) ->get(); // end-text-relevance $this->assertNotNull($movies); $this->assertCount(2, $movies); + $this->assertEquals('this is a love story', $movies[0]->plot); } - } From 3aa265b8f277b305142e325c44cb75cd995ab0ac Mon Sep 17 00:00:00 2001 From: rustagir Date: Mon, 22 Apr 2024 13:49:01 -0400 Subject: [PATCH 7/7] update tests to search for phrase --- .../read-operations/ReadOperationsTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/includes/fundamentals/read-operations/ReadOperationsTest.php b/docs/includes/fundamentals/read-operations/ReadOperationsTest.php index 6a453781f..a2080ec8f 100644 --- a/docs/includes/fundamentals/read-operations/ReadOperationsTest.php +++ b/docs/includes/fundamentals/read-operations/ReadOperationsTest.php @@ -30,8 +30,8 @@ protected function setUp(): void ['year' => 1999, 'countries' => ['Indonesia'], 'title' => 'Title 4'], ['year' => 1999, 'countries' => ['Canada'], 'title' => 'Title 5'], ['year' => 1999, 'runtime' => 30], - ['title' => 'movie_b', 'plot' => 'love is a long story'], ['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'], ]); } @@ -109,12 +109,12 @@ public function testFirst(): void public function testText(): void { // start-text - $movies = Movie::where('$text', ['$search' => 'love story']) + $movies = Movie::where('$text', ['$search' => '"love story"']) ->get(); // end-text $this->assertNotNull($movies); - $this->assertCount(2, $movies); + $this->assertCount(1, $movies); } /** @@ -124,13 +124,13 @@ public function testText(): void public function testTextRelevance(): void { // start-text-relevance - $movies = Movie::where('$text', ['$search' => 'love story']) + $movies = Movie::where('$text', ['$search' => '"love story"']) ->orderBy('score', ['$meta' => 'textScore']) ->get(); // end-text-relevance $this->assertNotNull($movies); - $this->assertCount(2, $movies); + $this->assertCount(1, $movies); $this->assertEquals('this is a love story', $movies[0]->plot); } }