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
2 changes: 2 additions & 0 deletions source/data-modeling/indexes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ indexes in the ``Restaurant`` model:
two documents with the same values for the ``_id`` field. You cannot
drop this index.

.. _mongoid_indexes_atlas_search:

Atlas Search Indexes
~~~~~~~~~~~~~~~~~~~~

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 6 additions & 1 deletion source/interact-data.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Interact with Data
Search Text </interact-data/text-search>
Transactions and Sessions </interact-data/transaction>
Nested Attributes </interact-data/nested-attributes>
Tutorial: Atlas Search </interact-data/atlas-search-tutorial>

In this section, you can learn how to use {+odm+} to interact with your
MongoDB data.
Expand All @@ -44,4 +45,8 @@ MongoDB data.
transactions to make atomic data changes.

- :ref:`mongoid-data-nested-attr`: Learn how to modify documents and
their associations in a single operation.
their associations in a single operation.

To learn how to integrate the Atlas Search feature into an application,
see the :ref:`Integrate Atlas Search into a {+ror+} App Tutorial
<mongoid-atlas-search-rails-tutorial>`.
330 changes: 330 additions & 0 deletions source/interact-data/atlas-search-tutorial.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,330 @@
.. _mongoid-atlas-search-rails-tutorial:

=========================================================
Tutorial: Integrate Atlas Search into a {+ror+} App
=========================================================

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

.. meta::
:keywords: code example, transform, pipeline

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

Overview
--------

In this tutorial, you can learn how to integrate :atlas:`Atlas Search
</atlas-search/>`, an advanced text search feature, into a {+ror+} app.

After you complete this tutorial, you have a fully functional search
feature embedded in your Rails app, allowing you to efficiently find
information.

Prerequisites
-------------

The tutorial builds on a template app that you can download from the
:github:`mongodb-atlas-with-ruby-on-rails-example GitHub repository
<mongodb-developer/mongodb-atlas-with-ruby-on-rails-example>` by running
the following command:

.. code-block:: bash

git clone https://github.com/mongodb-developer/mongodb-atlas-with-ruby-on-rails-example.git

Then, perform the following setup actions:

1. Create a MongoDB Atlas cluster. To learn how to create a cluster, see
the :ref:`mongoid-quick-start-rails-create-deployment` step of the
Rails Quick Start guide.

#. Update the app's ``config/mongoid.yml`` file with your own connection
string and set the default database to ``inspiration``, as shown the
following example configuration:

.. code-block:: yml

development:
clients:
default:
uri: mongodb+srv://<username>:<password>@<host>/inspiration

#. Start the Rails app by running the ``rails server`` command, then
complete the :guilabel:`New Idea` entry form to insert some sample
data into the ``inspiration.ideas`` collection.

.. tip:: Sample Data

To achieve the search functionality demonstrated later in
the tutorial, insert sample documents that contain some overlapping
terms in the ``name`` or ``description`` fields.

#. Create an Atlas Search index in Compass or the Atlas UI called
``inspiration`` with dynamic (default) mappings. To learn more about
creating Atlas Search indexes, see the
:ref:`mongoid_indexes_atlas_search` section of the Indexes guide.

Steps
-----

.. procedure::
:style: connected

.. step:: Configure the Atlas Search feature in your {+odm+} model.

First, update the ``Idea`` model to handle Atlas Search queries on
the ``ideas`` collection by defining the ``search`` method in the
model. The method ``self.search(query)`` defines a class method
called ``search`` that takes a single argument ``query`` and
returns the search results.

Open the ``app/models/idea.rb`` file and replace its contents with
the following code:

.. code-block:: ruby

class Idea
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
field :description, type: String
field :picture, type: String

def self.search(query)
aggregation_pipeline = [
{
"$search": {
"index": "inspiration",
"text": {
"query": query,
"path": ['name', 'description']
},
"sort": {
"score": { "$meta": "searchScore" }
}
}
},
{
"$limit": 20
}
]
results = collection.aggregate(aggregation_pipeline)

search_results = results.to_a
search_results.map do |result|
Idea.new(
id: result["_id"],
name: result["name"],
description: result["description"],
picture: result["picture"]
)
end
end
end

When you call ``idea.search("<example query>")``, {+odm+} performs the
following actions:

1. Performs a full-text search by using the ``inspiration`` index.
#. Runs the query across the ``name`` and ``description`` fields.
#. Sorts the results by their relevance scores.
#. Limits the number of results to ``20`` to improve performance
for queries on large collections.

The ``search_results`` variable then converts the raw results from
MongoDB into an array of hashes that can be mapped to ``Idea``
model instances and rendered in your view files.

.. step:: Add a Search action in your controller.

Now that you defined the Search query functionality in the
``Idea`` model, you must add an action to initiate queries.

Open the ``app/controllers/ideas_controller.rb`` file and add the
following action to your ``IdeasController`` before the ``private``
declaration:

.. code-block:: ruby

def search
@query = params[:query]
@ideas = @query.present? ? Idea.search(@query) : Idea.all
render :display_results
end

Now, when you submit a Search query, {+odm+} runs the
``search`` method in the ``Idea`` model. The
results are then rendered in your view files.

.. step:: Generate the Search controller.

Run the following command to generate the ``SearchesController``
and the ``display_results`` view file, which handle ``search``
requests and display the results, respectively:

Check failure on line 170 in source/interact-data/atlas-search-tutorial.txt

View workflow job for this annotation

GitHub Actions / TDBX Vale rules

[vale] reported by reviewdog 🐶 [MongoDB.Avoid] Don't use 'respectively'. Raw Output: {"message": "[MongoDB.Avoid] Don't use 'respectively'.", "location": {"path": "source/interact-data/atlas-search-tutorial.txt", "range": {"start": {"line": 170, "column": 41}}}, "severity": "ERROR"}

.. code-block:: bash

rails generate controller Searches display_results

Open the newly created ``searches_controller.rb`` file and replace
the contents with the following code:

.. code-block:: ruby

class SearchesController < ApplicationController
def display_results
query = params[:query]
@results = Idea.search(query)
end
end

Open the ``app/views/searches/display_results.html.erb`` file and
replace the contents with the following code, which renders the search results:

.. code-block:: html

<div class="search-results">
<h1>Search Results for "<%= params[:query] %>"</h1>

<% if @results.empty? %>
<p>No ideas found.</p>
<% else %>
<div class="idea-container">
<% @results.each do |result| %>
<div class="idea">
<h2><%= result.name %></h2>
<p><%= truncate(result.description, length: 150) %></p>
<img src="<%= result.picture %>" alt="<%= result.name %>" />

<p><%= link_to "View", idea_path(result.id) %></p>
</div>
<% end %>
</div>
<% end %>
</div>

<%= link_to "Back", ideas_path %>

Then, add the following code to your ``app/assets/stylesheets/application.css`` file to include
basic styling for the search results:

.. code-block:: css

.search-results {
width: 80%;
margin: 0 auto;
}
.idea-container {
display: flex;
flex-direction: column;
}
.idea {
padding: 20px;
border-bottom: 2px solid #ccc;
border-radius: 10px 10px 0 0;
margin-bottom: 10px;
}
.idea h2 {
margin: 0;
}
.idea p {
margin: 0;
}
.idea img {
width: 100px;
height: auto;
display: block;
}
ul {
list-style-type: none;
padding: 0;
}

.. step:: Create the Search form.

To enable Search queries directly in your application, open the
``app/views/ideas/index.html.erb`` file and add the following
code:

.. code-block:: html

<%= form_tag(search_results_path, method: :get, class: "form-inline") do %>
<div class="input-group mb-3">
<%= text_field_tag :query, params[:query], placeholder: "Search Ideas...", class: "form-control" %>
<div class="input-group-append">
<%= submit_tag "Search", class: "btn btn-primary text-white" %>
</div>
</div>
<% end %>

Add the following styling for the search bar to your ``application.css`` file:

.. code-block:: css

.input-group {
width: 100%;
}
.btn-primary {
background-color: #007bff;
border-color: #007bff;
color: white;
}
.btn-primary:hover {
background-color: #0056b3;
border-color: #004085;
}

.. step:: Update app routes for Search queries.

Replace the existing route in the ``config/routes.rb`` file with
following route to display search results:

.. code-block:: ruby

Rails.application.routes.draw do
root to: "ideas#index"
resources :ideas
get '/search_results', to: 'searches#display_results', as: "search_results"
end

.. step:: Start your application and run Search queries.

In your project directory, run the following command to start your
application:

.. code-block:: bash

rails server

Navigate to http://127.0.0.1:3000/ to view the landing page.

Check failure on line 306 in source/interact-data/atlas-search-tutorial.txt

View workflow job for this annotation

GitHub Actions / TDBX Vale rules

[vale] reported by reviewdog 🐶 [MongoDB.Time24h2Digits] Show the hours, minutes, and seconds with two digits each, even if the leading digit is 0 ('1:30'). Raw Output: {"message": "[MongoDB.Time24h2Digits] Show the hours, minutes, and seconds with two digits each, even if the leading digit is 0 ('1:30').", "location": {"path": "source/interact-data/atlas-search-tutorial.txt", "range": {"start": {"line": 306, "column": 34}}}, "severity": "ERROR"}

To submit a query, type a term or phrase in the search bar then
click the :guilabel:`Search` button. The following image depicts
the search results for the term ``"outdoor"``:

.. figure:: /includes/figures/atlas-search-tutorial-render.png
:alt: The rendered Search results

The search results depend on the documents in your
database. As the complexity of your data increases, you might need
to perform more advanced queries to narrow results. To learn more
about different Atlas Search queries and view examples, see the
:atlas:`Query Reference </atlas-search/query-ref/>` in the Atlas
documentation.

Conclusion
----------

In this tutorial, you learned how to integrate the Atlas Search feature
into a Rails application. This integration enhances usability and
functionality while improving user engagement.

To learn more about performing queries in {+odm+}, see the
:ref:`mongoid-interact-data` guides.
3 changes: 3 additions & 0 deletions source/quick-start-rails/next-steps.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@ Learn more about {+odm+} features from the following sections:

- :ref:`mongoid-interact-data`: Learn how to interact with your MongoDB
data by using {+odm+} models.

- :ref:`mongoid-atlas-search-rails-tutorial`: Learn how to integrate the
Atlas Search feature into your application.
Loading