ウェブエンジニア珍道中

日々の技術的に関する経験を書いていきます。脱線もしますが助けになれば幸いです。

docker-composeでのRails環境にElasticsearchを組み込む

dockerを用いたRailsの開発環境に新たにElasticsearhを組み込んだのでまとめます。

Dockerの設定

docker-compose.ymlを以下のように修正します。

version: '2'

services:
  rails:
    # ~ imageとか元々の設定(省略) ~ 

    # 追加
    depends_on:
      - elasticsearch

  # 追加
  elasticsearch:
    image: elasticsearch:5.6.10


  # 追加
  kibana:
    image: kibana
    ports:
      - 5601:5601
    depends_on:
      - elasticsearch

Elasticsearchが動くコンテナを追加して、depends_onで起動順を制御しています。

kibanaも入れています、ブラウザ上で操作・確認がしやすいからです。

Rails側の設定

gemを追加

続いてGemfileにelasticseach用のgemを追加します。使うgemはこちらです。

github.com

以下をGemfileに記述します。

gem 'elasticsearch-model', git: 'https://github.com/elasticsearch/elasticsearch-rails.git', branch: "5.x"
gem 'elasticsearch-rails', git: 'https://github.com/elasticsearch/elasticsearch-rails.git', branch: "5.x"
bundle install

branch: "5.x"でバージョンを指定しているのに注意して下さい。elasticsearchが今回5系を入れているためgemのバージョンも5系に合わせています。これを合わせないと動きません。最初6.xと5.xの組み合わせでハマりました。詳しくはこちら。

File: README — Documentation for elasticsearch-model (5.1.0)

設定ファイルを追加

config/initializers/elasticsearch.rbを用意し、以下を記述します。

Elasticsearch::Model.client =
  Elasticsearch::Client.new hosts: [
    {
      host: 'elasticsearch',
      port: '9200'
    }
]

このファイルで接続するためのhostとportを指定します。docker-composeで作成したため、hostはコンテナ名と同じelasticsearchでOKです。詳しくは割愛しますが、DNSが内部的に作られ解決してくれています。portはデフォルトで9200です。

Modelに組み込む

実際にElasticsearchを扱うModelに記述していきます。今回は例としてBookクラスに記述します。

require 'elasticsearch/model' # 追加

class Book
  include Elasticsearch::Model # 追加
end

実際に動かしてみる

これで必要最低限の準備が整いました。rails consoleでデータの入れ込みをしてみます。

docker-compose run rails rails c
[1] pry(main)> Book.__elasticsearch__.create_index!
# インデックスが作られる

[2] pry(main)> Book.__elasticsearch__.import
# 元のDB(mysqlなど)から1000件ずつ全データを取ってきてinsertする

Elasticsearch::Modelをincludeすることで上記のメソッドが使えるようになり、データの作成ができます。

試しに検索をしてみます。

[3] pry(main)> Book.__elasticsearch__.search(query: {match_all: {}}).records.to_a
=> [(Bookクラスのインスタンスの配列…)]
# 全件取得(elasticsearchのデフォルト設定により10件)されたBookモデルのインスタンスが取れる

[4] pry(main)> Book.__elasticsearch__.search(query: { match: { name: "hoge" } }).records.to_a
=> [(Bookクラスのインスタンスの配列…)]
# nameに"hoge"が含まれたデータを取得

__elasticsearch__.searchメソッドの引数にElasticsearchのクエリを入力することで検索ができます。これで最低限の環境を揃えることができました。

localhost:5061にアクセスすることでkibana上で確認することもできます。

f:id:te-nu:20180726194041p:plain

また今度はリレーション先のデータをimportする時の設定などをまとめたいと思います。では。

Elasticsearch実践ガイド (impress top gear)

Elasticsearch実践ガイド (impress top gear)