Rails + ElasticSearch 調査メモ


ElasticSearch

java8以上が必要 (ダウンロード)

# ESのインストール
$ brew install elasticsearch

# ESの起動
$ /usr/local/Cellar/elasticsearch/7.8.1/bin/elasticsearch
or
$ elasticsearch

# 動作確認
$ curl http://localhost:9200

プラグインの追加

  • kuromoji (分かち書き)
  • ICU (文字の正規化フィルター)
$ elasticsearch-plugin install https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-kuromoji/analysis-kuromoji-7.8.1.zip
$ elasticsearch-plugin install https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-7.8.1.zip


データ構造

RDBと比べたときのESの構造 (参考)

Cluster > Node > Index( = DB) > Type(=Table) >Document( =Row)


基本的な使い方

# index一覧
curl -X GET http://localhost:9200/_cat/indices

# index作成
curl -XPUT http://localhost:9200/インデックス名

# indexの削除
curl -XDELETE localhost:9200/インデックス名

# docの追加
curl -XPOST http://localhost:9200/インデックス名/タイプ名/ -d '{
    "field_01": "hoge1",
}'


# docの取得
curl -XGET http://localhost:9200/new_index/_search

curl -H "Content-Type: application/json" -XGET localhost:9200/インデックス名/_search\?pretty  -d '{"size":100}'

    ※?prettyで結果を整形して出力
    ※ -d '{"size":100}'で件数を指定しないとマックス10件しかでない。
    ※ jsonを送るときは「 -H "Content-Type: application/json"」が必要


# docの検索
curl -H "Content-Type: application/json" -XGET localhost:9200/インデックス名/_search\?pretty  -d'
{
  "query": {
    "match": {
      項目名: 検索値
    }
  }
}'


# docの追加
curl -H "Content-Type: application/json" -XPOST http://localhost:9200/インデックス名/new/ -d'{
  項目名: 値
}'


Kibana

リクエストビルダー的な機能があるので開発で必要なら入れる

# install
$ brew install kibana
$ brew info kibana

# 起動
$ kibana

# ダッシュボードにアクセス
http://localhost:5601/app/kibana#/dev_tools/console


参考リンク

RailsからElasticSearchを利用する

  • elasticsearch-rails gem を利用。
  • include Elasticsearch::Model してModel経由で操作する。
  • index名は環境で変わるように、index_name "articles-#{Rails.env}" と設定している。
# index作成
<Model名>.create_index

# DBのデータを全部インポートし直し
<Model名>__elasticsearch__.import

# データ検索例
<Model名>.search query:{ match_all: {}}
<Model名>.search query:{ match: {title:”hello”}}

Model変更処理の際にsidekiqをasync実行(ArticleIndexer.perform_async) → Redis にキューイングされて非同期で ElasticSearchのインデックスが作成される(models/concerns/article_searchable


sidekiq

非同期でのインデックス更新のために必要。
Redisにキューイングされて非同期でElasticSearchにインデックスされる。

$ brew install redis 

$ gem 'sidekiq'

$ bundle exec sidekiq -C config/sidekiq.yml

参考

ElasticSearch日本語用プラグインの話

・インデックスの設定の確認(analyzerを指定していればれで確認できる。)

curl -H "Content-Type: application/json"  http://localhost:9200/articles-test/_mappings\?pretty
curl -H "Content-Type: application/json"  http://localhost:9200/articles-test/\?pretty

・esでクエリーがどのように分割されるのか(分かち書き== tokenize)の確認

curl -H "Content-Type: application/json" -XGET localhost:9200/articles-test/_search\?pretty  -d'
{
  "query": {
    "match": {
      "title": "東京都"
    }
  }
}'

そもそも全文検索について

基本的には完全一致ではない。
全文検索は英語などだと、スペースで単語を区切り、その単語毎に分割してインデックスを作成する。
その分割した単語でマッチさせるため、完全一致で検索するとは限らない。

kuromojiとngramはこの分かち書きのための設定。ngramの方が一致率は高い。

icuでやってくれることは半角カナとかをうまく、普通の文字としてインデックスしてくれる。
日本語のUTF-8文字を上うまいこと変換してくれるフィルター的な..

全文検索について 参考リンク

https://dev.classmethod.jp/articles/es-02/
https://tech-blog.rakus.co.jp/entry/20191002/elasticsearch#Analyzer%E3%81%A8%E3%81%AF
https://medium.com/hello-elasticsearch/elasticsearch-833a0704e44b
https://qiita.com/shin_hayata/items/41c07923dbf58f13eec4

タームベースクエリ(完全一致)

filterとqueryの違い

query(full text search)は検索結果の取得にスコアを考慮しなし。
検索結果に関連性が高いかを示すスコアが大事な時は query を使うという感じ

スコアとは

検索結果の順位をどう決めるのか
一つの文書の中で該当検索語がよくマッチしていて、しかもそれは他の文書ではあんまり見られない該当文書のユニークな検索語で、しかもそれが短い文書であれば、マッチ度は高い
https://qiita.com/r4-keisuke/items/d653d26b6fc8b7955c05

ICUフィルターがしてくれること

https://medium.com/hello-elasticsearch/elasticsearch-c98fd9ce6a18
フィルターに設定して文字の正規化を行う

日本語用プラグインのインストール

Kuromojiインストール

/usr/local/Cellar/elasticsearch/7.8.1/bin/elasticsearch-plugin install https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-kuromoji/analysis-kuromoji-7.8.1.zip

ICU インストール

/usr/local/Cellar/elasticsearch/7.8.1/bin/elasticsearch-plugin install https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-7.8.1.zip

railsでの設定参考

https://qiita.com/chase0213/items/381b1eeacb849d93ecfd
https://qiita.com/yamashun/items/e1f2157e1b3cf3a716e3