Table of Contents
Elasticsearch Introduction
Install Elasticsearch
Install Elastic HQ
Create Rails Application
Add search
Search Highlight
Searchkick gem
自动建议
结论
Home Web Front-end HTML Tutorial Full text search in Rails using Elasticsearch

Full text search in Rails using Elasticsearch

Aug 31, 2023 am 08:41 AM
elasticsearch research all rails

In this article, I will show you how to implement full-text search using Ruby on Rails and Elasticsearch. Nowadays, everyone is accustomed to typing a search term and getting suggestions and highlighted results for the search term. Autocorrect is also a nice feature if what you're trying to search for is misspelled, as we've seen on sites like Google or Facebook.

Achieving all of this functionality using just a relational database like MySQL or Postgres is not straightforward. So we use Elasticsearch, which you can think of as a database built and optimized specifically for search. It is open source and built on Apache Lucene.

One of the best features of Elasticsearch is exposing its functionality using a REST API, so there are libraries that encapsulate this functionality for most programming languages.

Elasticsearch Introduction

Earlier, I mentioned that Elasticsearch is like a database for search. This will be useful if you are familiar with some of its terminology.

  • Field: A field is like a key-value pair. The value can be a simple value (string, integer, date) or a nested structure (such as an array or object). Fields are similar to columns in tables in relational databases.
  • Document: A document is a list of fields. It is a JSON document stored in Elasticsearch. It is like a row in a table in a relational database. Each document is stored in the index and has a type and unique ID.
  • Type: Types are like tables in relational databases. Each type has a list of fields that can be specified for documents of that type.
  • Index: Index is equivalent to a relational database. It contains multiple types of definitions and stores multiple documents.

One thing to note here is that in Elasticsearch, when you write a document to the index, the document fields are analyzed literally to make searching easy and fast. Elasticsearch also supports geolocation, so you can search for documents located within a certain distance of a given location. This is exactly how Foursquare implements search.

I would like to mention that Elasticsearch is built with high scalability in mind, so it is easy to build clusters with multiple servers and have high availability even if some servers fail. I won't go into detail on how to plan and deploy different types of clusters in this article.

Install Elasticsearch

If you are using Linux, you may be able to install Elasticsearch from one of the repositories. It can be used in APT and YUM.

If you are using a Mac, you can install it using Homebrew: brew install elasticsearch. After installing elasticsearch, you will see a list of related folders in the terminal:

Full text search in Rails using Elasticsearch

To verify that the installation is working properly, start it by typing elasticsearch in the terminal. Then run curl localhost:9200 in the terminal and you should see something similar to:

Full text search in Rails using Elasticsearch

Install Elastic HQ

Elastic HQ is a monitoring plugin that we can use to manage Elasticsearch from the browser, similar to phpMyAdmin for MySQL. To install it, just run in terminal:

/usr/local/Cellar/elasticsearch/2.2.0_1/libexec/bin/plugin -install royrusso/elasticsearch-HQ

After the installation is complete, navigate to http://localhost:9200/_plugin/hq in your browser:

Full text search in Rails using Elasticsearch

Click Connect and you will see a screen showing the cluster status: p>

Full text search in Rails using Elasticsearch

At this point, as you might expect, no indexes or documents have been created yet, but we do have a local instance of Elasticsearch installed and running.

Create Rails Application

I'm going to create a very simple Rails application where you add articles to a database so that we can perform a full text search on them using Elasticsearch. Start by creating a new Rails application:

rails new elasticsearch-rails

Next we use scaffolding to generate a new article resource:

rails generates scaffolding article title:string text:text

Now we need to add a new root route so that we can see the article list by default. Editconfig/routes.rb:

Rails.application.routes.draw do
  root to: 'articles#index'
  resources :articles
end

Create the database by running the command rake db:migrate. If you start rails server, open a browser, navigate to localhost:3000 and add some articles to the database, or just download the file db/seeds.rb with the dummy data I created so you don't have to spend a lot of time Fill in the form.

Now that we have our little Rails application containing the articles in the database, we're ready to add search functionality. We'll start by adding references to two official Elasticsearch Gems:

gem 'elasticsearch-model'
gem 'elasticsearch-rails'

On many websites, it is common to have a text box for search in the top menu of all pages. So I'm going to create a form section at app/views/search/_form.html.erb. As you can see, I'm sending the generated form using GET, so I can easily copy and paste the URL for a specific search.

<%= form_for :term, url: search_path, method: :get do |form| %>
  <p>
    <%= text_field_tag :term, params[:term] %>
    <%= submit_tag "Search", name: nil %>
  </p>
<% end %>

Add a reference to the form in the main site layout. Edit app/views/layouts/application.html.erb.

<body>
  <%= render 'search/form' %>
  <%= yield %>
</body>

Now we also need a controller to perform the actual search and display the results, so we run the command rails g new controller Search to generate it.

class SearchController < ApplicationController
  def search
    if params[:term].nil?
	  @articles = []
	else
	  @articles = Article.search params[:term]
	end
  end
end

As you can see, I'm calling the method search on the Article model. We haven't defined it yet, so if we try to perform a search at this point, we'll get an error. Also, we haven't added the SearchController's routes in the config/routes.rb file, so let's do this:

Rails.application.routes.draw do
  root to: 'articles#index'

  resources :articles
  get "search", to: "search#search"
end

If we look at the documentation for the gem 'elasticsearch-rails', we need to include two modules on the model to be indexed in Elasticsearch, in our case article.rb.

require 'elasticsearch/model'

class Article < ActiveRecord::Base
  include Elasticsearch::Model
  include Elasticsearch::Model::Callbacks
end

The first model injects the Search method we used in the previous controller. The second module integrates with ActiveRecord callbacks to index each instance of an article we save to the database, and it also updates the index if we modify or delete an article from the database. So it's all transparent to us.

If you previously imported data into the database, these articles are still not in the Elasticsearch index; only new ones will be automatically indexed. Therefore, we have to index them manually, which is easy if we launch rails console. Then we just need to run irb(main) > Article.import.

Full text search in Rails using Elasticsearch

Now we are ready to try out the search feature. If I type "ruby" and click search, the results are:

Full text search in Rails using Elasticsearch

Search Highlight

On many websites, you can see how the terms you searched for are highlighted on the search results page. This is easy to do using Elasticsearch.

Editapp/models/article.rband modify the default search method:

def self.search(query)
  __elasticsearch__.search(
    {
      query: {
        multi_match: {
          query: query,
          fields: ['title', 'text']
        }
      },
      highlight: {
        pre_tags: ['<em>'],
        post_tags: ['</em>'],
        fields: {
          title: {},
          text: {}
        }
      }
    }
  )
end

By default, the search method is defined by gem 'elasticsearch-models' and provides the proxy object __elasticsearch__ to access the wrapper class of the Elasticsearch API. Therefore, we can modify the default query using the standard JSON options provided by the documentation.

The search method will now wrap results that match the query with the specified HTML tag. To do this, we also need to update the search results page to safely render HTML tags. To do this, edit app/views/search/search.html.erb.

<h1>Search Results</h1>

<% if @articles %>
  <ul class="search_results">
    <% @articles.each do |article| %>
      <li>
	    <h3>
	      <%= link_to article.try(:highlight).try(:title) ?
		      article.highlight.title[0].html_safe : article.title,
              controller: "articles", action: "show", id: article._id %>
	    </h3>
	    <% if article.try(:highlight).try(:text) %>
          <% article.highlight.text.each do |snippet| %>
          <p><%= snippet.html_safe %>...</p>
        <% end %>
      <% end %>
    </li>
  <% end %>
</ul>
<% else %>
  <p>Your search did not match any documents.</p>
<% end %>

Add CSS styles to app/assets/stylesheets/search.scss for highlighted tags:

.search_results em {
  background-color: yellow;
  font-style: normal;
  font-weight: bold;
}

Try searching for "ruby" again:

Full text search in Rails using Elasticsearch

As you can see, highlighting search terms is easy, but not ideal because we need to send a JSON query and as the Elasticsearch documentation specifies, we don't have any kind of abstraction.

Searchkick gem

The Searchkick gem is provided by Instacart and is an abstraction on top of the official Elasticsearch gem. I'm going to refactor the highlighting functionality so we first add gem 'searchkick' to the gemfile. The first class we need to change is the Article.rb model:

class Article < ActiveRecord::Base
  searchkick
end

As you can see, it's much simpler. We need to reindex the article again and execute the command rake searchkick:reindex CLASS=Article. In order to highlight search terms, we need to pass an additional parameter from search_controller.rb to the search method.

class SearchController < ApplicationController
  def search
    if params[:term].nil?
	  @articles = []
	else
	  term = params[:term]
	  @articles = Article.search term, fields: [:text], highlight:  true
	end
  end
end

The last file we need to modify is views/search/search.html.erb because searchkick now returns results in a different format:

<h2>Search Results for: <i><%= params[:term] %></i></h2>

<% if @articles %>
<ul class="search_results">
  <% @articles.with_details.each do |article, details| %>
    <li>
	  <h3>
	    <%= link_to article.title, controller: "articles", action: "show", id: article.id %>
	  </h3>
      <p><%= details[:highlight][:text].html_safe %>...</p>
	</li>
  <% end %>
</ul>
<% else %>
  <p>Your search did not match any documents.</p>
<% end %>

Now it’s time to run the application again and test the search functionality:

Full text search in Rails using Elasticsearch

请注意,我输入了搜索词“dato”。我这样做的目的是为了向您展示,默认情况下,searchkick 设置为分析索引的文本,并且更允许拼写错误。

自动建议

自动建议或预先输入可预测用户将输入的内容,从而使搜索体验更快、更轻松。请记住,除非您有数千条记录,否则最好在客户端进行过滤。

让我们首先添加 typeahead 插件,该插件可通过 gem 'bootstrap-typeahead-rails' 获得,并将其添加到您的 Gemfile 中。接下来,我们需要向 app/assets/javascripts/application.js 添加一些 JavaScript,以便当您开始在搜索框中输入内容时,会出现一些建议。

//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require bootstrap-typeahead-rails
//= require_tree .

var ready = function() {
  var engine = new Bloodhound({
      datumTokenizer: function(d) {
          console.log(d);
          return Bloodhound.tokenizers.whitespace(d.title);
      },
      queryTokenizer: Bloodhound.tokenizers.whitespace,
      remote: {
          url: '../search/typeahead/%QUERY'
      }
  });

  var promise = engine.initialize();

  promise
      .done(function() { console.log('success'); })
      .fail(function() { console.log('error') });

  $("#term").typeahead(null, {
    name: "article",
    displayKey: "title",
    source: engine.ttAdapter()
  })
};

$(document).ready(ready);
$(document).on('page:load', ready);

关于前一个片段的一些评论。在最后两行中,因为我没有禁用涡轮链接,所以这是连接我想要在页面加载时运行的代码的方法。在脚本的第一部分,您可以看到我正在使用 Bloodhound。它是 typeahead.js 建议引擎,我还设置了 JSON 端点来发出 AJAX 请求来获取建议。之后,我在引擎上调用 initialize(),并使用其 id“term”在搜索文本字段上设置预输入。

现在,我们需要对建议进行后端实现,让我们从添加路由开始,编辑 app/config/routes.rb

Rails.application.routes.draw do
  root to: 'articles#index'

  resources :articles
  get "search", to: "search#search"
  get 'search/typeahead/:term' => 'search#typeahead'
end

接下来,我将在 app/controllers/search_controller.rb 上添加实现。

def typeahead
  render json: Article.search(params[:term], {
    fields: ["title"],
    limit: 10,
    load: false,
    misspellings: {below: 5},
  }).map do |article| { title: article.title, value: article.id } end
end

此方法返回使用 JSON 输入的术语的搜索结果。我只按标题搜索,但我也可以指定文章的正文。我还将搜索结果的数量限制为最多 10 个。

现在我们准备尝试 typeahead 实现:

Full text search in Rails using Elasticsearch

结论

如您所见,将 Elasticsearch 与 Rails 结合使用使搜索数据变得非常简单且快速。在这里,我向您展示了如何使用 Elasticsearch 提供的低级 gem,以及 Searchkick gem,这是一个隐藏了 Elasticsearch 工作原理的一些细节的抽象。

根据您的具体需求,您可能会很乐意使用 Searchkick 并快速轻松地实施全文搜索。另一方面,如果您有一些其他复杂的查询,包括过滤器或组,您可能需要了解有关 Elasticsearch 上查询语言的详细信息,并最终使用较低级别的 gem 'elasticsearch-models' 和 'elasticsearch-导轨”。

The above is the detailed content of Full text search in Rails using Elasticsearch. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

PHP Tutorial
1502
276
How to use php extension Sphinx for full text search How to use php extension Sphinx for full text search Jul 29, 2023 am 10:05 AM

How to use PHP extension Sphinx for full-text search Full-text search is one of the common requirements in modern web applications. In order to satisfy users' efficient query and retrieval of data, we can use Sphinx, a powerful open source search engine, to implement the full-text search function. Sphinx is written in C++ and provides PHP extensions to facilitate our use in PHP projects. This article will introduce how to use the PHP extension Sphinx for full-text search

How to use PHP to implement full-text search and keyword extraction functions How to use PHP to implement full-text search and keyword extraction functions Sep 05, 2023 pm 02:00 PM

How to use PHP to implement full-text search and keyword extraction functions Full-text search and keyword extraction are common functions in modern websites and applications, which can provide users with a better search experience and relevant recommendations. In PHP, we can use full-text indexing and keyword extraction technology to achieve these functions. This article will introduce how to use PHP to implement full-text search and keyword extraction functions, and provide corresponding code examples. Implementation of full-text search function Full-text search refers to searching for records containing specified keywords in text content. exist

How to use MongoDB to implement full-text search function of data How to use MongoDB to implement full-text search function of data Sep 19, 2023 pm 05:48 PM

How to use MongoDB to implement the full-text search function of data Introduction: With the rapid development of the information age, the full-text search function has become a necessary function for many applications. As a popular NoSQL database, MongoDB also provides powerful full-text search capabilities. This article will introduce how to use MongoDB to implement the full-text search function of data and provide relevant code examples. 1. Introduction to MongoDB full-text search function MongoDB’s full-text search function is based on MongoDB’s text search function.

How to use PHP and SQLite for full-text search and indexing strategies How to use PHP and SQLite for full-text search and indexing strategies Jul 29, 2023 pm 08:45 PM

How to use PHP and SQLite for full-text search and indexing strategies Introduction: In modern application development, full-text search capabilities are indispensable in many fields. Whether on blogs, news websites, or e-commerce platforms, users are accustomed to using keywords to search. Therefore, to improve user experience and provide better search results, we need to provide full-text search capabilities using appropriate search and indexing strategies. In this article, we will explore how to use PHP and SQLite databases to implement full-text search and

Log analysis and exception monitoring based on Elasticsearch in PHP Log analysis and exception monitoring based on Elasticsearch in PHP Oct 03, 2023 am 10:03 AM

Summary of log analysis and exception monitoring based on Elasticsearch in PHP: This article will introduce how to use the Elasticsearch database for log analysis and exception monitoring. Through concise PHP code examples, it shows how to connect to the Elasticsearch database, write log data to the database, and use Elasticsearch's powerful query function to analyze and monitor anomalies in the logs. Introduction: Log analysis and exception monitoring are

In-depth study of Elasticsearch query syntax and practical combat In-depth study of Elasticsearch query syntax and practical combat Oct 03, 2023 am 08:42 AM

In-depth study of Elasticsearch query syntax and practical introduction: Elasticsearch is an open source search engine based on Lucene. It is mainly used for distributed search and analysis. It is widely used in full-text search of large-scale data, log analysis, recommendation systems and other scenarios. When using Elasticsearch for data query, flexible use of query syntax is the key to improving query efficiency. This article will delve into the Elasticsearch query syntax and give it based on actual cases.

How to use PHP and Elasticsearch to highlight search results How to use PHP and Elasticsearch to highlight search results Jul 17, 2023 pm 09:24 PM

How to use PHP and Elasticsearch to achieve highlighted search results Introduction: In the modern Internet world, search engines have become the main way for people to obtain information. In order to improve the readability and user experience of search results, highlighting search keywords has become a common requirement. This article will introduce how to use PHP and Elasticsearch to achieve highlighted search results. 1. Preparation Before starting, we need to ensure that PHP and Elasticsearch have been installed and configured correctly.

Explain InnoDB Full-Text Search capabilities. Explain InnoDB Full-Text Search capabilities. Apr 02, 2025 pm 06:09 PM

InnoDB's full-text search capabilities are very powerful, which can significantly improve database query efficiency and ability to process large amounts of text data. 1) InnoDB implements full-text search through inverted indexing, supporting basic and advanced search queries. 2) Use MATCH and AGAINST keywords to search, support Boolean mode and phrase search. 3) Optimization methods include using word segmentation technology, periodic rebuilding of indexes and adjusting cache size to improve performance and accuracy.

See all articles