Skip to content

Commit 0f8474e

Browse files
rustagirGromNaN
andauthored
DOCSP-35959: search text (#2889)
* DOCSP-35959: search text * code fixes * JM and CC PR fixes 1 * fix controller code * move index creation into setup * Fix index creation in tests * update tests to search for phrase --------- Co-authored-by: Jérôme Tamarelle <[email protected]>
1 parent eea4950 commit 0f8474e

File tree

2 files changed

+156
-1
lines changed

2 files changed

+156
-1
lines changed

docs/fundamentals/read-operations.txt

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ This guide shows you how to perform the following tasks:
2929

3030
- :ref:`laravel-retrieve-matching`
3131
- :ref:`laravel-retrieve-all`
32+
- :ref:`laravel-retrieve-text-search`
3233
- :ref:`Modify Find Operation Behavior <laravel-modify-find>`
3334

3435
Before You Get Started
@@ -175,6 +176,121 @@ Use the following syntax to run a find operation that matches all documents:
175176
more information about ``take()``, see the :ref:`laravel-modify-find` section of this
176177
guide.
177178

179+
.. _laravel-retrieve-text-search:
180+
181+
Search Text Fields
182+
------------------
183+
184+
A text search retrieves documents that contain a **term** or a **phrase** in the
185+
text-indexed fields. A term is a sequence of characters that excludes
186+
whitespace characters. A phrase is a sequence of terms with any number
187+
of whitespace characters.
188+
189+
.. note::
190+
191+
Before you can perform a text search, you must create a :manual:`text
192+
index </core/indexes/index-types/index-text/>` on
193+
the text-valued field. To learn more about creating
194+
indexes, see the :ref:`laravel-eloquent-indexes` section of the
195+
Schema Builder guide.
196+
197+
You can perform a text search by using the :manual:`$text
198+
</reference/operator/query/text>` operator followed
199+
by the ``$search`` field in your query filter that you pass to the
200+
``where()`` method. The ``$text`` operator performs a text search on the
201+
text-indexed fields. The ``$search`` field specifies the text to search for.
202+
203+
After building your query with the ``where()`` method, chain the ``get()``
204+
method to retrieve the query results.
205+
206+
This example calls the ``where()`` method on the ``Movie`` Eloquent model to
207+
retrieve documents in which the ``plot`` field contains the phrase
208+
``"love story"``. To perform this text search, the collection must have
209+
a text index on the ``plot`` field.
210+
211+
.. tabs::
212+
213+
.. tab:: Query Syntax
214+
:tabid: query-syntax
215+
216+
Use the following syntax to specify the query:
217+
218+
.. literalinclude:: /includes/fundamentals/read-operations/ReadOperationsTest.php
219+
:language: php
220+
:dedent:
221+
:start-after: start-text
222+
:end-before: end-text
223+
224+
.. tab:: Controller Method
225+
:tabid: controller
226+
227+
To see the query results in the ``browse_movies`` view, edit the ``show()`` function
228+
in the ``MovieController.php`` file to resemble the following code:
229+
230+
.. io-code-block::
231+
:copyable: true
232+
233+
.. input::
234+
:language: php
235+
236+
class MovieController
237+
{
238+
public function show()
239+
{
240+
$movies = Movie::where('$text', ['$search' => '"love story"'])
241+
->get();
242+
243+
return view('browse_movies', [
244+
'movies' => $movies
245+
]);
246+
}
247+
}
248+
249+
.. output::
250+
:language: none
251+
:visible: false
252+
253+
Title: Cafè de Flore
254+
Year: 2011
255+
Runtime: 120
256+
IMDB Rating: 7.4
257+
IMDB Votes: 9663
258+
Plot: A love story between a man and woman ...
259+
260+
Title: Paheli
261+
Year: 2005
262+
Runtime: 140
263+
IMDB Rating: 6.7
264+
IMDB Votes: 8909
265+
Plot: A folk tale - supernatural love story about a ghost ...
266+
267+
Title: Por un puèado de besos
268+
Year: 2014
269+
Runtime: 98
270+
IMDB Rating: 6.1
271+
IMDB Votes: 223
272+
Plot: A girl. A boy. A love story ...
273+
274+
...
275+
276+
A text search assigns a numerical :manual:`text score </reference/operator/query/text/#text-score>` to indicate how closely
277+
each result matches the string in your query filter. You can sort the
278+
results by relevance by using the ``orderBy()`` method to sort on the
279+
``textScore`` metadata field. You can access this metadata by using the
280+
:manual:`$meta </reference/operator/aggregation/meta/>` operator:
281+
282+
.. literalinclude:: /includes/fundamentals/read-operations/ReadOperationsTest.php
283+
:language: php
284+
:dedent:
285+
:start-after: start-text-relevance
286+
:end-before: end-text-relevance
287+
:emphasize-lines: 2
288+
289+
.. tip::
290+
291+
To learn more about the ``orderBy()`` method, see the
292+
:ref:`laravel-sort` section of this guide.
293+
178294
.. _laravel-modify-find:
179295

180296
Modify Behavior

docs/includes/fundamentals/read-operations/ReadOperationsTest.php

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace App\Http\Controllers;
66

77
use App\Models\Movie;
8+
use Illuminate\Support\Facades\DB;
89
use MongoDB\Laravel\Tests\TestCase;
910

1011
class ReadOperationsTest extends TestCase
@@ -15,7 +16,10 @@ protected function setUp(): void
1516

1617
parent::setUp();
1718

18-
Movie::truncate();
19+
$moviesCollection = DB::connection('mongodb')->getCollection('movies');
20+
$moviesCollection->drop();
21+
$moviesCollection->createIndex(['plot' => 'text']);
22+
1923
Movie::insert([
2024
['year' => 2010, 'imdb' => ['rating' => 9]],
2125
['year' => 2010, 'imdb' => ['rating' => 9.5]],
@@ -26,6 +30,9 @@ protected function setUp(): void
2630
['year' => 1999, 'countries' => ['Indonesia'], 'title' => 'Title 4'],
2731
['year' => 1999, 'countries' => ['Canada'], 'title' => 'Title 5'],
2832
['year' => 1999, 'runtime' => 30],
33+
['title' => 'movie_a', 'plot' => 'this is a love story'],
34+
['title' => 'movie_b', 'plot' => 'love is a long story'],
35+
['title' => 'movie_c', 'plot' => 'went on a trip'],
2936
]);
3037
}
3138

@@ -94,4 +101,36 @@ public function testFirst(): void
94101
$this->assertNotNull($movie);
95102
$this->assertInstanceOf(Movie::class, $movie);
96103
}
104+
105+
/**
106+
* @runInSeparateProcess
107+
* @preserveGlobalState disabled
108+
*/
109+
public function testText(): void
110+
{
111+
// start-text
112+
$movies = Movie::where('$text', ['$search' => '"love story"'])
113+
->get();
114+
// end-text
115+
116+
$this->assertNotNull($movies);
117+
$this->assertCount(1, $movies);
118+
}
119+
120+
/**
121+
* @runInSeparateProcess
122+
* @preserveGlobalState disabled
123+
*/
124+
public function testTextRelevance(): void
125+
{
126+
// start-text-relevance
127+
$movies = Movie::where('$text', ['$search' => '"love story"'])
128+
->orderBy('score', ['$meta' => 'textScore'])
129+
->get();
130+
// end-text-relevance
131+
132+
$this->assertNotNull($movies);
133+
$this->assertCount(1, $movies);
134+
$this->assertEquals('this is a love story', $movies[0]->plot);
135+
}
97136
}

0 commit comments

Comments
 (0)