Elasticsearch is an OSS full-text search engine developed by Elastic. You can quickly extract a document containing the desired word from a large number of documents.
Elasticsearch creates an index as a storage location for your data. It's like a table in a relational database.
First, install a dedicated gem to handle Rails models in Elasticsearch. Write the following in Gemfile and bundle install.
gem 'elasticsearch-model', github: 'elastic/elasticsearch-rails'
gem 'elasticsearch-rails', github: 'elastic/elasticsearch-rails'
After bundle install, create an index in Elasticsearch. Include Elasticsearch :: Model in the model you want to search.
class Article < ActiveRecord::Base
  include Elasticsearch::Model
end
Your model is now ready to work with Elasticsearch. You can create an index with code like this:
Article.__elasticsearch__.create_index! force:true
In Elasticsearch, the data in the index is called a document. Enter the data you want to search in the index.
Import the document into Elasticsearch with the following code.
Article.import
The document will now be registered in the Elasticsearch index.
To search the document, submit a query to Elasticsearch. You can query Elasticsearch from Rails by writing:
response = Article.search 'hoge'
You can search the document by specifying the search string as an argument.
If you receive the parameters from the front desk and search, you can write as follows.
def index
  @articles = Article.search(params)
end
When it comes to actually operating the service, it is necessary to update the Elasticsearch document when the record is updated on the Rails side.
First of all, to simply update the Elasticsearch documentation, implement:
Article.first.__elasticsearch__.update_document
There is another method called delete_document, which you can use to delete a document.
You can also update the document automatically when you update the record, without having to write it explicitly as above. In elasticsearch-model which is a gem, if Elasticsearch :: Model :: Callbacks is included in Model, it will send a query to update the Elasticsearch document when the record is updated.
class Article
  include Elasticsearch::Model
  include Elasticsearch::Model::Callbacks
end
Actually create the processing around the search of the Article model.
article-m/app/models/concerns/article/searchable.rb
require 'active_support/concern'
module Article::Searchable
  extend ActiveSupport::Concern
  included do
    include Elasticsearch::Model
    
    index_name "article"
    settings index: {
      number_of_shards: 1,
      number_of_replicas: 0
    } do
      mapping _source: { enabled: true } do
        indexes :id, type: 'integer', index: 'not_analyzed'
        indexes :title, type: 'string'
        indexes :content, type: 'text'
      end
    end
  end
  module ClassMethods
    def create_index!(options={})
      client = __elasticsearch__.client
      client.indices.delete index: "article" rescue nil if options[:force]
      client.indices.create index: "article",
      body: {
        settings: settings.to_hash,
        mappings: mappings.to_hash
      }
    end
  end
end
In the module, include Elasticsearch :: Model to use convenient methods.
Write the index name in index_name and the index settings in settings. number_of_shards and number_of_replicas are shard and replica settings related to fault tolerance and performance.
mapping determines how the index is defined. It's like a table schema in an RDB.
create_index! is a helper that actually creates an index. Since elasticsearch.client can take the object of Elasticsearch client, You can perform various operations via this client.
Include the created module in the model.
article-m/app/models/article.rb
class Article < ActiveRecord::Base
  include Article::Searchable
  def self.search_message(keyword)
    if keyword.present?
      query = {
        "query": {
          "match": {
            "message": keyword
          }
        }
      }
      Article.__elasticsearch__.search(query)
    else
      Article.none
    end
  end
end
Assemble a search query from the keywords you received and pass it to Article.elasticsearch.search. By calling elasticsearch.search on the Article model, elasticsearch-rails and elasticsearch-model will throw a query.
The controller looks like this:
article-m/app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
  def search
    @keyword = params[:keyword]
    @articles = Article.search_message(@keyword).paginate(page: params[:page])
  end
The above is an example of incorporating Elasticsearch into a Rails app.
Run Elasticsearch on Rails using elastisearch-rails [for beginners] [Summary of what I did to incorporate Elasticsearch into the Rails app search process](https://qiita.com/minamijoyo/items/31118d4aa3d06513ad4d#elasticsearch%E3%82%92rails%E3%82%A2%E3%83% 97% E3% 83% AA% E3% 81% AB% E7% B5% 84% E3% 81% BF% E8% BE% BC% E3% 82% 80)
Recommended Posts