全文検索エンジンElasticsearchについてまとめてみました

全文検索エンジンElasticsearchについてまとめてみました

どうもこんにちはkoheiです。

今回は業務でElasticsearchを使用する案件があり、私自身疑問に思い、調べたことについてまとめたいと思います。

 

 

・Elasticsearchってなに?
・全文検索エンジン?
・DB、NoSQLと何が違うの?

 

 

そんな疑問に答えられたらと思います。

Elasticsearchとは?

Elasticsearch は Elastic 社が開発しているオープンソースの全文検索エンジンです。

現在最新のバージョンは7.3.x。

logstash > Elasticsearch > kibanaが良く使われるみたいです。いわゆるElastic Stackってやつです。Elastic 社が押している使い方かと思います。(以下URL参照してみてください。)

https://www.elastic.co/jp/products/elastic-stack

実際、私も上記の様な組み合わせで使用しました。

検索エンジンといったらGoogleをすぐに思い出します。

JVM上で動作する

Elasticsearchはjavaで実装されてます。JavaメインのWeb系エンジニアの僕としては親しみやすかったです。

JVM上で動作するので、ヒープメモリの設定等でチューニングをしていくことになります。

細かいことを言うと、検索スピードが売りにしているElasticsearchだとおもっているので、ガベージコレクション(GC)の頻度をリサーチしてチューニングしないと動作が遅くなってしまうので必須かなと思いました。

※Logstash、KibanaもJVMで動作します。

Apache Luceneを使用

ElasticsearchはApache Lucene(アパッチ ルシーン)という全文検索クラスライブラリを利用しています。オープンソースなので簡単に利用できます。

なるほどといったところです。深堀りしたいです。

投入できるデータ形式はjson

投入できるデータ形式はjsonです。よってスキーマレス。

つまり、事前にデータ定義をしなくても良いです。

NoSQLデータベースのMongoDBと同じですね。

ただし、注意しなければいけない点として、事前にデータ定義をした場合、検索性能が上がるみたいです。

私が利用したときも、事前にデータ定義をしました。ElasticsearchではMappinng(後述)を決めることです。

Mapping情報は後から変更ができないので、新たにMappingを変更したい場合は、

 

  1. インデックス(後述)を削除
  2. 新たなMappingを定義したインデックスを作成
  3. インデックスにデータを投入

 

以上のステップを経なければいけません。。

結局、スキーマレスの恩恵は受けれなかったです。

ここで、ElasticsearchとNoSQLデータベースは何が違うのかという疑問が生まれました。

Elasticsearchは全文検索エンジンと呼ばれるけど、NoSQLとは呼ばれないのか?

NoSQLではないのか?

かぎりなく近いみたいです。

ただ、圧倒的に全文検索が強力で、かなり集計できるので検索エンジンと呼ばれているのだと思います。

NoSQLと違い、RESTAPIでデータのやり取りができ、Kibanaと連携できるのも大きいと感じます。

細かいことを言うと、Elasticseach では基本的にドキュメント定義(mapping と呼ばれる)の構成を変えられないため、新しいmappingに切り替えるには、新しく全データを流し込む必要があります。

同じJson形式でデータを持つNoSQLのMongoDBでは新しいカラムを追加できるのでスキーマレスです。

ElasticsearchはJson形式でありながら完全にスキーマレスではない(ドキュメント定義をしなければスキーマレスだが、大体定義するのが一般的に思えます)のがNoSQLと呼ばれない理由の1つかと個人的には思いました。

Rest APIで通信する。

データの登録、変更、参照をする際はElasticsearchのRest APIを叩くになります。

Rest APIとは、リソースとURIが紐付いていて、リソースの操作はHTTPメソッド(GET・POST・PUT・DELETE)を利用するインターフェイスになります。

私はコマンドラインからcurlコマンドを叩いてました。

参考例は以下になります。

  • バージョン確認
[root@ ~]# curl -XGET http://localhost:9200/
{ 			
 "name" : "(割愛)", 			
 "cluster_name" : "elasticsearch", 			
 "cluster_uuid" : "(割愛)", 			
 "version" : { 			
   "number" : "6.6.1", 			
   "build_flavor" : "oss", 			
   "build_type" : "rpm", 			
   "build_hash" : "(割愛)", 			
   "build_date" : "2019-02-13T17:10:04.160291Z", 			
   "build_snapshot" : false, 			
   "lucene_version" : "7.6.0", 			
   "minimum_wire_compatibility_version" : "5.6.0", 			
   "minimum_index_compatibility_version" : "5.0.0" 			
  }, 			
 "tagline" : "You Know, for Search" 			
} 			

  • template更新
[root@ ~]# curl -XPUT -H "Content-Type: application/json" -d@/etc/logstash/template.json http://localhost:9200/_template/(template名)?pretty            
[root@ ~]# curl -XGET http://localhost:9200/_template/(template名)?pretty
{ 			
 "(template名)" : { 			
   "order" : 0, 			
   "index_patterns" : [ 			
     "*" 			
    ], 			
   "settings" : { 			
     "index" : { 			
       "number_of_shards" : "1", 			
       "number_of_replicas" : "0" 			
      } 			
    }, 			
   "mappings" : { }, 			
   "aliases" : { } 			
  } 			
} 		
[root@ ~]# cat /etc/logstash/ template.json 			
{ 			
   "template": "*", 			
   "settings": { 			
       "number_of_shards": 1, 			
       "number_of_replicas" : 0 			
    } 			
} 	

  • index情報確認
[root@ ~]# curl -XGET http://localhost:9200/(index名)?pretty
{ 			
 "(index名)" : { 			
   "aliases" : { }, 			
   "mappings" : { 			
     "doc" : { 			
       "properties" : { 			
         "@timestamp" : { 			
           "type" : "date" 			
         }, 			
         "@version" : { 			
           "type" : "text", 			
           "fields" : { 			
             "keyword" : { 			
                "type" : "keyword", 			
                "ignore_above" : 256 			
             } 			
           } 			
         }, 			
         "(定義field名)" : { 			
           "type" : "text", 			
           "fields" : { 			
             "keyword" : { 			
                "type" : "keyword", 			
                "ignore_above" : 256 			
             } 			
           } 			
         } 			
       } 			
      } 			
    }, 			
   "settings" : { 			
     "index" : { 			
       "creation_date" : "(割愛)", 			
       "number_of_shards" : "1", 			
       "number_of_replicas" : "0", 			
       "uuid" : "(割愛)", 			
       "version" : { 			
         "created" : "(割愛)" 			
       }, 			
       "provided_name" : "(index名)" 			
      } 			
    } 			
  } 			
} 	

Elasticsearchの詳しくは公式ドキュメントを参考にしてみてください。(以下URL)

https://www.elastic.co/guide/en/elasticsearch/reference/current/rest-apis.html

独自の言語がある。

私はKibanaと連携し使ってました。

KibanaではDev Toolsという画面があって、curlコマンドの様なコマンドを打つことで、Kibana上でElasticsearchのデータにアクセスし、確認することができました。

よくわからずに使っていたのですが、これはElasticsearchがクエリの実行に使用できるJSON形式のドメイン固有言語(Query DSL)みたいです。

使い方は公式ドキュメントを参照してみてください。(以下URL)

https://www.elastic.co/guide/jp/elasticsearch/reference/current/gs-query-lang.html

今現在、ベーシック以上のライセンス(後述)では一般的なSQLも使用できます。

深くは試していませんが、RDB経験のある方のほうが大多数かと思うので検索しやすいかと思います。

データは物理的、論理的な概念で分けられる

ElasticsearchではCluster、Node、Index、Type、Document、Shardという単語をよく耳にします。

よく一般的なRDBで例えられることが多いですが、私は使っていて物理的、論理的に分けたほうがわかりやすいなと思いました。

以下のような感じになります。

  • 物理的

  1. Cluster(クラスタ):1つ以上のNodeから成り立つ。

  2. Node(ノード):1サーバで1つのNodeを持ち、1以上のシャードを持つ

  3. Shard(シャード):プライマリ(書き込み専用)とレプリカ(プライマリの複製、読み込み専用)が存在し、この2つは同一ノードには共存できない(クラスタのステータスが黄色になります)。※高可用性、分散処理になることでパフォーマンスの向上。

  • 論理的

  1. Index(インデックス):ドキュメントのコレクション。“>1つのIndexは複数のShardから成り立つ

  2. Type(タイプ):6系からは1つのIndexに1つしか定義できないみたいです。※デフォルト値「doc_」

  3. Document(ドキュメント):データの基本単位、index/type内に、必要な数のドキュメントを格納できる。

 

※パワポで適当に作ったので見た目は多目にみてください

 

Typeについては実質的廃止かと思います。私はデフォルトから変更したことがありません。

クラスタ構成前提で作られてる

Elasticsearchはクラスタ構成前提で作られているので、容易にクラスタ構成を組むことができます。

クラスタ構成とは:上記の概念図のように複数のサーバを連携させることで全体で1台のサーバであるかのように動作させる技術。利用者側からは複数台で動いていることは意識しなくても利用できる。

クラスタ構成を組むことによって、検索用のレプリカシャード(プライマリシャードの複製)を作ることができるので検索のパフォーマンスを上げることができます。よって、スケーラビリティにも優れてます

余談(X-Packについて)

Elasticsearch 6.3.0 から X-Pack で利用できた機能がデフォルトで含まれるようになったみたいです。

そのことについては調べれば出てくるのですが、OSSには入っていないです。

OSSをインストールして、セキュリティの設定をしたかったのですが、OSSでは利用できないことが判明しました。

Elasticsearchは4つのサブスクリプションプランがあります。

  • オープンソース(OSS)
  • ベーシック
  • ゴールド
  • プラチナ

X-Packの機能を利用したい方は、ベーシックプラン以降を利用する必要があります。

ライセンスを取得しなければ利用できないということです。

※X-Pack:セキュリティ、アラート、モニタリング、レポート、グラフの機能をインストールしやすい1つのパッケージにまとめたElastic Stackの拡張機能

Elastic Stackまとめ

簡単に概要のみまとめたいと思います。Logstash、Kibanaは実際に使ってました。深堀りしたい。。

Logstash

リアルタイムのパイプライン機能を備えたオープンソースのデータ収集エンジンです。

Rubyスクリプトで動作しますが、Jrubyが同梱されており、JVM上で動きます。

なぜJVM上で動かす必要があるかというと、Javaの豊富なライブラリを利用できることにあるからです。

ぱっと見た感じですが、実際にDBアクセスするためにJDBCドライバを使用してます。

Beats

私は使用したことがありませんが、データ取り込みを行うプラットフォームだそうです。

インプットに特化しており、取り込んだデータをLogstashで取得、変換後みたいな流れで使われるそうです。

Kibana

Elasticsearchのデータを可視化するツールです。

ブラウザはChromeじゃないといけなかった気がします。

簡単にデータをいろんなグラフで表現できるのは便利かと思いました。

気になったこと

以下、列挙します。知っている方教えて下さい。。

  • Elasticsearchの設定ファイル(elasticsearch.yml)で設定できる項目がたくさんあるのですが、それがまとまったドキュメントがないように思える。調査に苦労しました。
  • Query DSLは私が使っていたみたいにKibanaのDev Toolsでのみ利用可能なのか?

実際使ってみた感想

実際にElasticsearchにデータ投入からのKibanaで可視化までが非常に早く、費用対効果は高いかなといった印象です。

学習コストも低いかなと思いました。

実際にどのくらいのデータ量で検索スピードがどのくらいか等は今後試していきたいと思います。

個人的には、Elastic系がJVM上で動作するので親しみやすく、技術的な面で勉強になりました。

あと、RDBしか扱ってこなかったので、DB自体の全体像をつかめたのも大きいかと思います。

書籍も読むことがおすすめです

私は実際、公式ドキュメントを読みながら使い方について調べましたが、ある時点から限界を感じました。

日本語版はありますが、英語版のほうが詳しく書いてるので翻訳に時間かかります。

よって、はじめての方は概要を掴むためにも書籍を読むことをおすすめします。

ただ、公式ドキュメントも充実しているのでなんとかなります。詳しくしりたいという方は以下、参考に読んでみてください。

 
 
人気記事:【最新】Elastic Stack学習におすすめの本5選