Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions source/includes/interact-data/text-search.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# start-text-index-model
class Dish
include Mongoid::Document

field :name, type: String
field :description, type: String

index description: 'text'
end
# end-text-index-model

# start-term
Dish.where('$text' => {'$search' => 'herb'})
# end-term

# start-phrase
Dish.where('$text' => {'$search' => "\"serves 2\""})
# end-phrase

# start-exclude
Dish.where('$text' => {'$search' => 'vegan -tofu'})
# end-exclude
4 changes: 4 additions & 0 deletions source/interact-data.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Interact with Data

Specify a Query </interact-data/specify-query>
Modify Query Results </interact-data/modify-results>
Search Text </interact-data/text-search>
Transactions and Sessions </interact-data/transaction>

In this section, you can learn how to use {+odm+} to interact with your
Expand All @@ -27,5 +28,8 @@ MongoDB data.
- :ref:`mongoid-data-modify-results`: Learn how to modify the way that
{+odm+} returns results from queries.

- :ref:`mongoid-data-text-search`: Learn how to perform efficient
searches on text fields.

- :ref:`mongoid-data-txn`: Learn how to perform multi-document
transactions to make atomic data changes.
213 changes: 213 additions & 0 deletions source/interact-data/text-search.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
.. _mongoid-data-text-search:

===========
Search Text
===========

.. facet::
:name: genre
:values: reference

.. meta::
:keywords: ruby framework, odm, crud, filter, code example

.. contents:: On this page
:local:
:backlinks: none
:depth: 2
:class: singlecol

Overview
--------

In this guide, you can learn how to use {+odm+} to run a **text
search**. A text search allows you to efficiently query fields that have
string values.

MongoDB provides text indexes to support text search queries on
fields that have string values or values that are arrays of string
elements. To learn more about text indexes, see :manual:`Text Indexes on
Self-Managed Deployments </core/indexes/index-types/index-text/>` in the
{+server-manual+}.

.. note:: Atlas Search

This guide focuses on text search. If your database is hosted on
MongoDB Atlas, you can use the Atlas Search feature
to perform more powerful and flexible text searches. To learn more
about Atlas Search, see the :atlas:`Atlas Search Overview
</atlas-search/atlas-search-overview/>` in the Atlas documentation.

You can run a text search by performing the following steps:

1. Define a text index on a model.
#. Create the text index on the target collection.
#. Perform a text search query.

The following sections describe how to perform each of these actions.

Define a Text Index on Your Model
---------------------------------

.. TODO link to indexes page

Use the ``index`` macro to specify the text index in your model
definition. The following code creates a ``Dish`` model class that
includes a text index on the ``description`` field:

.. literalinclude:: /includes/interact-data/text-search.rb
:start-after: start-text-index-model
:end-before: end-text-index-model
:language: ruby
:emphasize-lines: 7
:dedent:

.. note::

You must specify the index type as a string, as shown by ``'text'``
in the preceding code.

Create the Text Index
---------------------

Next, you must create the text index in your collection. You can
create the index by using an interface such as the :atlas:`Atlas UI
</atlas-ui/indexes>` or :compass:`Compass </indexes>`. If you are using
the Rails framework to develop your application, you can run the following
Rake task to create the index based on your model specification:

.. code-block:: bash

bundle exec rake db:mongoid:create_indexes

Perform Text Searches
---------------------

To perform a text search, use the ``$text`` evaluation query operator,
followed by the ``$search`` field in your query filter. The ``$text`` operator
performs a text search on the text indexed fields. The ``$search`` field
specifies the text to search in the text indexed fields. To learn more
about this operator, see the :manual:`$text reference
</reference/operator/query/text>` in the {+server-manual+}.

.. _mongoid-term-search:

Search by a Term
~~~~~~~~~~~~~~~~

To search for a term, specify the term as a string in your query filter.
To search for multiple terms, separate each term with spaces in the string.

.. note:: Searching for Multiple Terms

When searching for multiple terms, {+odm+} returns
documents with at least one of the terms in text indexed fields.

Suppose you search by using the string ``'cake coffee cream'``. The
following list describes values that match this text query:

- ``'Has strong coffee notes.'``
- ``'Good for creamy coffee fans.'``
- ``'A rich but light cake.'``
- ``'A creamy coffee cake with cranberries.'``

The following example runs a text search for ``description`` values that contain
the term ``'herb'``:

.. io-code-block::
:copyable: true

.. input:: /includes/interact-data/text-search.rb
:start-after: start-term
:end-before: end-term
:language: rust
:dedent:

.. output::
:language: none
:visible: false

# Sample output
Copy link
Collaborator

@mcmorisi mcmorisi Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: Is this # Sample output line necessary to include?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we dont provide sample data, I thought this might be useful to include. I can also make the examples more simple or shorter.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine to leave as is, appreciate the explanation!

{"_id":"...","description":"A bright, herb-based salad. A perfect starter for vegetarians and vegans.","name":"Kale Tabbouleh"}
{"_id":"...","description":"Grilled whole fish stuffed with herbs and pomegranate seeds. Serves 3-4.","name":"Herbed Whole Branzino"}

.. tip::

Although the search term was ``'herb'``, the method also matches
descriptions containing ``'herbs'`` because a MongoDB text index uses *suffix
stemming* to match similar words. To learn more about how
MongoDB matches terms, see :manual:`Text Index Properties
</core/indexes/index-types/index-text/text-index-properties/>` in the
{+server-manual}.

Search by a Phrase
~~~~~~~~~~~~~~~~~~

To search for a phrase, specify the phrase with escaped quotes as a
string in your query filter. If you don't add escaped quotes around the
phrase, {+odm+} runs a :ref:`term search <mongoid-term-search>`.

.. tip::

Escaped quotes are a backslash character (``\``) followed by a double
quote character (``"``).

The following example runs a text search for ``description`` values that
contain the phrase ``"serves 2"``:

.. io-code-block::
:copyable: true

.. input:: /includes/interact-data/text-search.rb
:start-after: start-phrase
:end-before: end-phrase
:language: rust
:dedent:

.. output::
:language: none
:visible: false

# Sample output
{"_id":"...","description":"A vegetarian take on the classic dish that uses lentils as a base. Serves 2.","name":"Shepherd’s Pie"}
{"_id":"...","description":"Baked trout seasoned with garlic, lemon, dill, and, of course, butter. Serves 2.","name":"Garlic Butter Trout"}

Search with Excluded Terms
~~~~~~~~~~~~~~~~~~~~~~~~~~

For each term or phrase to exclude from your text search,
specify the term or phrase prefixed with a minus sign (``-``) as a string in
your query filter.

.. important::

You must search for at least one term to exclude
terms from your search. If you don't search for any terms, {+odm+}
doesn't return any documents.

The following example runs a text search for ``description`` values that
contain the term ``'vegan'``, but do not contain the term ``'tofu'``:

.. io-code-block::
:copyable: true

.. input:: /includes/interact-data/text-search.rb
:start-after: start-exclude
:end-before: end-exclude
:language: rust
:dedent:

.. output::
:language: none
:visible: false

# Sample output
{"_id":"...","description":"A bright, herb-based salad. A perfect starter for vegetarians and vegans.","name":"Kale Tabbouleh"}

Additional Information
----------------------

To learn more about constructing query filters, see
:ref:`mongoid-data-specify-query`.

.. TODO link to CRUD guide
Loading