Skip to content

Commit df89288

Browse files
authored
DOCSP-30538: text search (#90)
1 parent dd03137 commit df89288

File tree

5 files changed

+500
-4
lines changed

5 files changed

+500
-4
lines changed

source/fundamentals/crud/read-operations.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Read Operations
1010
/fundamentals/crud/read-operations/retrieve
1111
/fundamentals/crud/read-operations/query
1212
/fundamentals/crud/read-operations/cursor
13+
/fundamentals/crud/read-operations/text-search
1314

1415
..
1516
/fundamentals/crud/read-operations/count
@@ -18,13 +19,13 @@ Read Operations
1819
/fundamentals/crud/read-operations/skip
1920
/fundamentals/crud/read-operations/limit
2021
/fundamentals/crud/read-operations/project
21-
/fundamentals/crud/read-operations/text
2222
/fundamentals/crud/read-operations/changestream
2323

2424

2525
- :ref:`rust-query-guide`
2626
- :ref:`rust-retrieve-guide`
2727
- :ref:`rust-cursor-guide`
28+
- :ref:`rust-search-text-guide`
2829

2930
.. - :ref:`rust-query-guide`
3031
.. - :ref:`rust-count-guide`
@@ -33,5 +34,4 @@ Read Operations
3334
.. - :ref:`rust-skip-guide`
3435
.. - :ref:`rust-limit-guide`
3536
.. - :ref:`rust-project-guide`
36-
.. - :ref:`rust-search-text-guide`
3737
.. - :ref:`rust-monitor-changes-guide`
Lines changed: 368 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,368 @@
1+
.. _rust-search-text-guide:
2+
3+
===========
4+
Search Text
5+
===========
6+
7+
.. facet::
8+
:name: genre
9+
:values: reference
10+
11+
.. meta::
12+
:keywords: code example, full text, string search
13+
14+
.. contents:: On this page
15+
:local:
16+
:backlinks: none
17+
:depth: 2
18+
:class: singlecol
19+
20+
Overview
21+
--------
22+
23+
In this guide, you can learn how to use the {+driver-short+} to run a text search.
24+
A text search allows you to efficiently query fields with string values.
25+
26+
.. important::
27+
28+
MongoDB text search differs from the more powerful Atlas Search
29+
feature. To learn more, see the :atlas:`Atlas Search documentation
30+
</atlas-search/>`.
31+
32+
This guide includes the following sections:
33+
34+
- :ref:`Sample Data for Examples <rust-text-sample-data>` presents
35+
the sample data that is used by the text search examples
36+
37+
- :ref:`Text Index <rust-text-index>` describes how to create a text
38+
index on a string-valued field
39+
40+
- :ref:`Text Search <rust-text-search>` describes how to perform text
41+
searches with different search criteria
42+
43+
- :ref:`Aggregation <rust-search-text-aggregation>` describes how to
44+
perform text searches by using aggregation pipelines
45+
46+
- :ref:`Additional Information <rust-crud-text-addtl-info>`
47+
provides links to resources and API documentation for types
48+
and methods mentioned in this guide
49+
50+
.. _rust-text-sample-data:
51+
52+
Sample Data for Examples
53+
------------------------
54+
55+
The examples in this guide use the following ``Dish`` struct as a model
56+
for documents in the ``menu`` collection:
57+
58+
.. literalinclude:: /includes/fundamentals/code-snippets/crud/text.rs
59+
:start-after: start-dish-struct
60+
:end-before: end-dish-struct
61+
:language: rust
62+
:dedent:
63+
64+
The examples use the following sample documents that describe
65+
dishes you can order at a restaurant:
66+
67+
.. code-block:: json
68+
:copyable: false
69+
70+
{ "name": "Shepherd’s Pie", "description": "A vegetarian take on the classic dish that uses lentils as a base. Serves 2." },
71+
{ "name": "Green Curry", "description": "A flavorful Thai curry, made vegetarian with tofu. Vegetarian and vegan friendly." },
72+
{ "name": "Herbed Branzino", "description": "Grilled whole fish stuffed with herbs and pomegranate seeds. Serves 3-4." },
73+
{ "name": "Kale Tabbouleh", "description": "A bright, herb-based salad. A perfect starter for vegetarians and vegans." },
74+
{ "name": "Garlic Butter Trout", "description": "Baked trout seasoned with garlic, lemon, dill, and, of course, butter. Serves 2." }
75+
76+
.. _rust-text-index:
77+
78+
Text Index
79+
----------
80+
81+
Before you perform a text search, you must create a **text index** on
82+
the collection. A text index specifies the string or string array field
83+
on which you can perform text searches.
84+
85+
The examples in this guide perform text searches on the
86+
``description`` field of documents in the ``menu`` collection. To enable
87+
text searches on the ``description`` field, create a text index as shown
88+
in the following code:
89+
90+
.. literalinclude:: /includes/fundamentals/code-snippets/crud/text.rs
91+
:language: rust
92+
:dedent:
93+
:start-after: begin-idx
94+
:end-before: end-idx
95+
96+
.. _rust-text-search:
97+
98+
Text Search
99+
-----------
100+
101+
A text search retrieves documents that contain a specified **term** or
102+
**phrase** in the value of the indexed field. A term is a sequence of
103+
characters that excludes whitespace characters. A phrase is a sequence
104+
of terms with any number of whitespace characters.
105+
106+
To perform a text search, include the ``$text`` evaluation query operator,
107+
followed by the ``$search`` field in your query filter. The ``$text`` operator
108+
specifies that you are performing a text search on the text-indexed
109+
fields. The ``$search`` field specifies the term or phrase to search for
110+
in the text-indexed field or fields.
111+
112+
Query filters for text searches use the following format:
113+
114+
.. code-block:: rust
115+
116+
let filter = doc! { "$text": { "$search": "<search term or phrase>" } };
117+
118+
.. _rust-text-term:
119+
120+
Search for a Term
121+
~~~~~~~~~~~~~~~~~
122+
123+
To search for a term, specify the term as a string in your query filter.
124+
To search for multiple terms, separate each term with a space.
125+
126+
.. note::
127+
128+
When searching for multiple terms, the ``find()`` method returns any
129+
document in which the text-indexed field or fields contain at least
130+
one of the terms.
131+
132+
For example, if your search terms are ``"one two
133+
three"``, MongoDB returns documents in which the indexed field
134+
contains ``"one"``, ``"two"``, ``"three"``, or more than one of these terms.
135+
136+
Example
137+
```````
138+
139+
The following example performs a search for documents in which the
140+
``description`` field contains the term ``"herb"``:
141+
142+
.. io-code-block::
143+
:copyable: true
144+
145+
.. input:: /includes/fundamentals/code-snippets/crud/text.rs
146+
:start-after: begin-by-term
147+
:end-before: end-by-term
148+
:language: rust
149+
:dedent:
150+
151+
.. output::
152+
:language: none
153+
:visible: false
154+
155+
Dish { name: "Kale Tabbouleh", description: "A bright, herb-based salad. A perfect starter for vegetarians and vegans." }
156+
Dish { name: "Herbed Branzino", description: "Grilled whole fish stuffed with herbs and pomegranate seeds. Serves 3-4." }
157+
158+
.. tip::
159+
160+
Even though the search term is ``"herb"``, the text search also matches
161+
documents in which the ``description`` field contains ``"herbs"``.
162+
This is because a MongoDB text index uses suffix stemming to match
163+
similar words. To learn more about how MongoDB matches terms, see
164+
:manual:`Index Entries </core/index-text/#index-entries>` in the
165+
Server manual.
166+
167+
.. _rust-text-phrase:
168+
169+
Search for a Phrase
170+
~~~~~~~~~~~~~~~~~~~
171+
172+
To search for a phrase, specify the phrase with escaped quotes in your
173+
query filter:
174+
175+
.. code-block:: rust
176+
177+
let filter = doc! { "$text": { "$search": "\"<some phrase>\"" } };
178+
179+
If you don't add escaped quotes around the phrase, the
180+
search performs a :ref:`term search <rust-text-term>`.
181+
182+
Example
183+
```````
184+
185+
The following example performs a search for documents in which the
186+
``description`` field contains the phrase ``"serves 2"``:
187+
188+
.. io-code-block::
189+
:copyable: true
190+
191+
.. input:: /includes/fundamentals/code-snippets/crud/text.rs
192+
:start-after: begin-by-phrase
193+
:end-before: end-by-phrase
194+
:language: rust
195+
:dedent:
196+
197+
.. output::
198+
:language: none
199+
:visible: false
200+
201+
Dish { name: "Shepherd’s Pie", description: "A vegetarian take on the classic dish that uses lentils as a base. Serves 2." }
202+
Dish { name: "Garlic Butter Trout", description: "Baked trout seasoned with garlic, lemon, dill, and, of course, butter. Serves 2." }
203+
204+
Exclude Terms from Search
205+
~~~~~~~~~~~~~~~~~~~~~~~~~
206+
207+
To specify a term or phrase you want to exclude from your text search,
208+
prefix it with a minus sign in your query filter:
209+
210+
.. code-block:: rust
211+
212+
let filter = doc! { "$text": { "$search": "<term> -<excluded term>" } };
213+
214+
.. important::
215+
216+
You must search for at least one term or phrase to exclude
217+
other terms from your search. If you only exclude terms, the
218+
search doesn't return any documents.
219+
220+
Example
221+
```````
222+
223+
The following example performs a search for documents in which the
224+
``description`` field contains the term ``"vegan"``, but does not
225+
contain the term ``"tofu"``:
226+
227+
.. io-code-block::
228+
:copyable: true
229+
230+
.. input:: /includes/fundamentals/code-snippets/crud/text.rs
231+
:start-after: begin-exclude-term
232+
:end-before: end-exclude-term
233+
:language: rust
234+
:dedent:
235+
236+
.. output::
237+
:language: none
238+
:visible: false
239+
240+
Dish { name: "Kale Tabbouleh", description: "A bright, herb-based salad. A perfect starter for vegetarians and vegans." }
241+
242+
Sort by Relevance
243+
~~~~~~~~~~~~~~~~~
244+
245+
A text search assigns a numerical text score to indicate how closely
246+
each result matches the string in your query filter. A higher text score
247+
indicates that the result is more relevant to your query. To reveal the text
248+
score in your output, use a projection to retrieve the ``textScore``
249+
field from the metadata. You can sort the text score in descending order
250+
by specifying a sort on the ``textScore`` metadata field.
251+
252+
Example
253+
```````
254+
255+
This example performs the following actions:
256+
257+
- Performs a search for documents in which the ``description`` field contains the term ``"vegetarian"``
258+
- Sorts the results in descending order on text score
259+
- Includes only the ``name`` and ``score`` fields in the output
260+
261+
.. io-code-block::
262+
:copyable: true
263+
264+
.. input:: /includes/fundamentals/code-snippets/crud/text.rs
265+
:start-after: begin-sort-relevance
266+
:end-before: end-sort-relevance
267+
:language: rust
268+
:dedent:
269+
270+
.. output::
271+
:language: none
272+
:visible: false
273+
274+
Document({"name": String("Green Curry"), "score": Double(0.9166666666666667)})
275+
Document({"name": String("Kale Tabbouleh"), "score": Double(0.5625)})
276+
Document({"name": String("Shepherd’s Pie"), "score": Double(0.5555555555555556)})
277+
278+
.. _rust-search-text-aggregation:
279+
280+
Aggregation
281+
-----------
282+
283+
You can include the ``$text`` evaluation query operator in a
284+
:manual:`$match </reference/operator/aggregation/match/>` aggregation
285+
stage to perform a text search in an aggregation pipeline.
286+
287+
The following sections demonstrate how to perform text searches by using
288+
aggregation pipelines instead of the ``find()`` method.
289+
290+
Match a Search Term
291+
~~~~~~~~~~~~~~~~~~~
292+
293+
The following example uses an aggregation to perform a search for
294+
documents in which the ``description`` field contains the term
295+
``"herb"``:
296+
297+
.. io-code-block::
298+
:copyable: true
299+
300+
.. input:: /includes/fundamentals/code-snippets/crud/text.rs
301+
:start-after: begin-agg-term
302+
:end-before: end-agg-term
303+
:language: rust
304+
:dedent:
305+
306+
.. output::
307+
:language: none
308+
:visible: false
309+
310+
Document({"_id": ObjectId("..."), "name": String("Kale Tabbouleh"), "description": String("A bright, herb-based salad. A perfect starter for vegetarians and vegans.")})
311+
Document({"_id": ObjectId("..."), "name": String("Herbed Branzino"), "description": String("Grilled whole fish stuffed with herbs and pomegranate seeds. Serves 3-4.")})
312+
313+
Sort by Relevance
314+
~~~~~~~~~~~~~~~~~
315+
316+
This example uses an aggregation to perform the following actions:
317+
318+
- Performs a search for documents in which the ``description`` field contains the term ``"vegetarian"``
319+
- Sorts the results in descending order on text score
320+
- Includes only the ``name`` and ``score`` fields in the output
321+
322+
.. io-code-block::
323+
:copyable: true
324+
325+
.. input:: /includes/fundamentals/code-snippets/crud/text.rs
326+
:start-after: begin-agg-relevance
327+
:end-before: end-agg-relevance
328+
:language: rust
329+
:dedent:
330+
331+
.. output::
332+
:language: none
333+
:visible: false
334+
335+
Document({"name": String("Green Curry"), "score": Double(0.9166666666666667)})
336+
Document({"name": String("Kale Tabbouleh"), "score": Double(0.5625)})
337+
Document({"name": String("Shepherd’s Pie"), "score": Double(0.5555555555555556)})
338+
339+
.. _rust-crud-text-addtl-info:
340+
341+
Additional Information
342+
----------------------
343+
344+
For a runnable example that uses the ``find()`` method, see the
345+
:ref:`rust-find-usage` usage example.
346+
347+
To learn more about the operations in this guide, see the
348+
following documentation:
349+
350+
- :ref:`rust-query-guide`
351+
- :ref:`rust-retrieve-guide`
352+
- :ref:`rust-aggregation`
353+
- :ref:`rust-indexes`
354+
- :manual:`Text Indexes </core/index-text/>` in the Server manual
355+
- :manual:`$text </reference/operator/query/text/>` in the Server manual
356+
- :manual:`$meta </reference/operator/aggregation/meta/>` in the Server manual
357+
358+
API Documentation
359+
~~~~~~~~~~~~~~~~~
360+
361+
To learn more about the methods and types mentioned in this
362+
guide, see the following API documentation:
363+
364+
- `find() <{+api+}/struct.Collection.html#method.find>`__
365+
- `FindOptions <{+api+}/options/struct.FindOptions.html>`__
366+
- `Cursor <{+api+}/struct.Cursor.html>`__
367+
- `clone_with_type() <{+api+}/struct.Collection.html#method.clone_with_type>`__
368+
- `aggregate() <{+api+}/struct.Collection.html#method.aggregate>`__

0 commit comments

Comments
 (0)