Skip to content

Instantly share code, notes, and snippets.

@gtaiyou24
Last active July 29, 2021 07:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gtaiyou24/55e26e34c37753b890b0f042df3b624f to your computer and use it in GitHub Desktop.
Save gtaiyou24/55e26e34c37753b890b0f042df3b624f to your computer and use it in GitHub Desktop.
Elasticsearchの構成・機能のまとめ

Near Realtime(NRT)

ElasticSearchは"ほぼリアルタイム"の検索プラットフォームです。 というのもdocumentをindexして検索できるまでに通常1分間時間がかかる

Cluster

一つ以上のnodeサーバの集合のこと。リレーショナルデータベースでいうDataBaseに当たる。 [役割]

  • 投入するデータをすべてのnodeサーバで分散して保持
  • 各nodeサーバをまたぐインデックスの提供
  • 各nodeサーバをまたぐデータの検索 [注意事項]
  • Clusterはユニーク名で識別されるので名前はとても重要
  • nodeを新しくそのクラスタに追加するときに設定したクラスタ名を指定する。そのためユニークなクラスタ名にする必要がある
  • ユニークなクラスタ名を指定したクラスタを独立して複数持てる

Node

NodeはClusterの一要素である一つのサーバのこと。データの保持を行い、クラスタのインデックスと検索能力に関係する [注意事項]

  • クラスタと同じくNodeもユニークな名前で識別される。デフォルトはUUID(Universally Unique IDentifier)。

Index

文字列を格納するdocumentの集合のこと。リレーショナルデータベースでいうテーブルになる。 [注意事項]

  • Indexはローケースの名前で識別される。以下の用途で名前が使われる
    • インデックスの実行を行う際のindexの指定
    • indexに格納されているドキュメントに対しての検索、更新、削除
  • 一つのクラスタ内にたくさんのIndexを定義できる

Type

カラムフィールドを持つDocumentのために定義される。リレーショナルデータベースでいうカラムに当たる。

Document

documentはインデックスされる基本の単位のデータのこと。リレーショナルデータベースでいうレコードに当たる。

Shards&Replicas

一つのIndexは一つのnodeのハードウェアの制限を超えることができる膨大な量のデータを潜在的に保持できる。

1TBのディスク容量をとる1億数のドキュメントをもつようなIndexでは、検索が遅れるかもしれない ↓ Shards: indexを複数個に小分けする単位。デフォルトでは5つ [Shardが重要な理由]

  1. コンテンツ量を分割・減少させられる
  2. 複数のshardを並列処理できる ¥-------- ネットワーク/クラウドではいつダウンしてもおかしくない。shard/nodeが何かしらの理由で消えたり、接続できなくなったときのために、一つ以上のIndexのshardのコピーを取っておくことができる ↓ Replicas: 一つ以上のindexのshardコピーのこと。デフォルトでは1つのreplicaをもつ [Replicaが必要な理由]
  3. shard/nodeが消えたときのためにコピーをとって高い能力を発揮する

Elasticsearchとは

Elasticsearch

  • 分散型RESTfull検索/分析エンジン
    • 検索:構造型から非構造型、地理情報、メトリックなど多様なタイプの検索に対応
    • 分析:蓄積されたデータからAgregationAPIを使用して傾向やパターンを探せる

Elasticsearchの特徴

 

クラスタ:スケーラブルで柔軟な設計
クラスタ構成が前提で実装されているため、同一のクラスタ名で用意するだけでレプリカが自動で実行される。また、データのマッピング(Mapping)を定義せずにデータの投入が可能なため、蓄積した後に利用したい形・型に変更できる。
REST-API
RESTインターフェースですべての入出力が可能。
Kibana:協力な可視化ツールの提供
Shield: セキュリティ管理
Watcher: データの監視

ElasticsearchとRDBMSの違い

RDBMS Elasticsearch
条件にマッチしたデータを正確に返す 条件との関連性の高いデータを返す

※クエリとデータの関連度はTF/IDF(Term Frequency/Inverse Document Frequency)をもとにスコアを算出している


Elasticsearchの起動・停止

Elasticsearchの起動方法

$ cd ~path/to/elasticsearch-5.2.0/bin
$ ./elasticsearch -Ecluster.name=起動するクラスタ名 -Enode.name=起動するノード名

Elasticsearchの停止方法

Elasticsearchを起動しているコンソール上で「Control-C」を押せば停止

Cluster

Cluster Healthの確認

$ curl -XGET 'localhost:9200/_cluster/health?pretty'
{
  "cluster_name" : "bigdata_navi_bot", #起動しているクラスタ名
  "status" : "yellow", #クラスタの状態
  "timed_out" : false,
  "number_of_nodes" : 1,
  "number_of_data_nodes" : 1,
  "active_primary_shards" : 5,
  "active_shards" : 5,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 5,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 50.0
}

status: green,yellow,redのいずれかになる

  • green:問題なし
  • yellow: すべてのデータが利用可能。しかしいくつかのreplicasがまだ割り当てられていない状態
  • red:なんらかの理由でいくつかのデータが利用できない状態。機能はするが修正する必要がある

Cluster Stateの確認

全クラスタの包括的な状態の情報を取得

$ curl -XGET 'http://localhost:9200/_cluster/state?pretty'

特定のクラスタ状態情報を取得

$curl -XGET 'http://localhost:9200/_cluster/state/{metrics}/{index1,index2,...}?pretty'

metrics: カンマ(,)区切りのリスト

  • version:クラスタ状態のバージョンを表示
  • master_node:マスターノードを表示
  • nodes:ノード一覧を表示
  • routing_table:routing_tableを表示。もしカンマ区切りのindexリストを指定しているなら、そのindexのrouting_tableを表示
  • metadata:メタデータを表示。もしカンマ区切りのindexリストを指定しているなら、そのindexのメタデータを表示

Cluster Statsの確認

クラスタの統計情報を取得

$ curl -XGET 'http://localhost:9200/_cluster/stats?human&pretty'

Clusterのシャード配置の制御

$ curl -XPOST 'http://localhost:9200/_cluster/reroute' -d '{
     "commands": [
          {
               "move": { #shardを他のノードに移動
                    "index":"", "shard":,
                    "form_node":"", "to_node":""
               }
          },
          {
               "cancel": { #shardの割り当てを中止する
                    "index":"", "shard":,
                    "node":, "allow_primary":
               }
          },
          {
               "allocate_replica": { #未配置のreplica・shardをノードに割り当てる
                     "index":"", "shard":, "node":""
               }
          }
     ]
}'

Node

Index

Indexの作成

indexの作成

$ curl -XPUT 'localhost:9200/インデックス名?pretty' -H 'Content-Type: application/json' -d '{
     "settings": { #作成するインデックスの設定を定義
          "number_of_shards" : 3, #shardの数。デフォルトは5
          "number_of_replicas" : 2 #replicaの数。デフォルトは1
     }
}'

indexの作成(マッピング定義付き)

$ curl -XPUT 'localhost:9200/インデックス名?pretty' -H 'Content-Type: application/json' -d '{
     "settings": {
          "number_of_shards" : 3,
          "number_of_replicas" : 2
     },
     "mappings": { #作成するインデックスのマッピングを定義
          "タイプ名": {
               "properties": {
                    "フィールド名": {"type": "text"}
               }
          }
     }
}'

Indexの削除

$ curl -XDELETE 'localhost:9200/削除するインデックス名?pretty'

Indexの取得

インデックスの情報を取得

$ curl -XGET 'localhost:9200/取得するインデックス名?pretty'

特定のインデックスの情報を取得

$ curl -XGET 'localhost:9200/取得するインデックス名/_settings,_mappings,...?pretty'

全てのIndexの取得

$ curl -XGET 'localhost:9200/_cat/indices?v&pretty'

Indexの存在確認

$ curl -XGET 'localhost:9200/確認するインデックス名/_settings,_mappings,...?pretty'

Index APIの開閉

$ curl -XPOST 'localhost:9200/インデックス名/_close?pretty' #read/writeの操作をブロック
$ curl -XPOST 'localhost:9200/インデックス名/_open?pretty' #closeを解除

Indexの分割(shrink)

詳細「Shrink Index」

IndexのRollover

詳細「Rollover Index」

Index Aliases

詳細「Index Aliases」

Index設定の変更

詳細「Update Indices Settings」

$ curl -XPUT 'localhost:9200/インデックス名/_settings' -d '{
     "index": { #更新の内容
          "number_of_replicas": 4
     }
}'

Index設定の取得

$ curl -XGET 'localhost:9200/インデックス名/_settings?pretty'
$ curl -XGET 'localhost:9200/インデックス名1,インデックス名2,.../_settings?pretty'
$ curl -XGET 'localhost:9200/_all/_settings?pretty'

ワイルドカードにマッチするインデックスの設定を取得

$ curl -XGET 'localhost:9200/hogeho-*/_settings?pretty'

Indexの分析

詳細「Analyze」

Indexテンプレート

詳細「Index Template」


Mapping

Mappingの変更

詳細「Put Mapping」

Mappingの取得

詳細「Get Mapping」

Mappingフィールドの取得

詳細「Get Field Mapping」

Types(型)の存在確認

詳細「Types Exists」


Replicaの設定


Indexの監視

Mappingとは

マッピングとは、 インデックス構造の定義を行う方法である。 次の定義をするためにマッピングを使用する

  • どのStringフィールドをfull textフィールドとして扱うか
  • フィールドは数、データ、位置情報を含むか
  • ドキュメントのすべてのフィールドの値のうちどれを_allフィールドにインデックス化するか
  • 格納するデータの型、フォーマット
  • 動的フィールドの変更

Mapping Types

各インデックスは、一つもしくはそれ以上のmapping typesを保持している。このmapping typesはインデックスのドキュメントをロジカルグループに分けるために使われる。ユーザ文書はuserタイプへ、ブログの投稿はblogpostタイプへ保存されるという具合だ。 それぞれのmapping typeは

  • Meta-fields:このフィールドはドキュメントのメタデータをカスタマイズするために使われる。
    • 例)_index, _type, _id, _source
  • FieldsもしくはProperties:各Mapping Typeはフィールドのリストかpropertiesを含んでいる。
    • 例) userタイプは、title, name, ageフィールドを含むだろう。
    • 例) blogpostタイプは、title, body, user_id, createdフィールドを含むだろう を持っている

Field datatypes

各Fieldsは次のようなデータタイプを持てる

  • シンプルなタイプ:text, keyword, date, long, double, boolean, ip
  • 階層的なデータタイプ :JSONオブジェクト
  • 特殊なタイプ:geo_point, geo_shape, completion また、同じフィールドでも違い用途に使えるようにすることができる。

Elasticsearchで使用できるデータタイプはこちら

メタフィールド

各ドキュメントはメタデータを持っている。いくつかのMeta-fieldの動作はmapping typeが作られるときにカスタマイズすることができる。

Elasticsearchで使用できるメタデータはこちら


Mappingパラメータ

Elasticsearchで使用できるMappingパラメータはこちら


Dynamic Mapping

Single document APIs

ドキュメントの追加(index化)・更新(reindex化)

# id値が存在したら以下のJSONデータで更新
# 無ければ追加する
$ curl -XPUT 'localhost:9200/インデックス名/タイプ名/id値?pretty&pretty' -H 'Content-Type: application/json' -d '{
     "user": "John Doe",
     "post_date": "2009-11-15T14:12:12",
     "message" : "trying out Elasticsearch"
}'
# 以下のJSONデータを追加
$ curl -XPOST 'localhost:9200/インデックス名/タイプ名?pretty&pretty' -H 'Content-Type: application/json' -d '{
     "user": "John Doe",
     "post_date": "2009-11-15T14:12:12",
     "message" : "trying out Elasticsearch"
}'
  • ドキュメントの追加・更新の実行時に、もし指定したインデックスが作成されていなければ自動的に作成する。同様に、もし指定したタイプ名が存在しなかったら、動的タイプ(dynamic type)マッピングを自動的に作成する。
  • mapping自身とても柔軟かつスキーマフリーである。新しいフィールドは、自動的にマッピングのタイプ定義に明記される。
  • 自動的にインデックスを作成したくなければ、action.auto_create_indexをfalseにすればよい。同様に、自動マッピングを作成したくなければ、index.mapper.dynamicをfalseにすればよい。

ドキュメントの取得

ドキュメントの削除

ドキュメントの更新


Multi-document APIs

The Search API

データの検索は、基本的に2つの方法がある

  1. REST request URI
  2. REST request body

ここでは以下のtypeのindexに対して検索を行うものとする

{    
"account_number": 0,
"balance": 16623,
"firstname": "Bradshaw",
"lastname": "Mckenzie",
"age": 29,
"gender": "F",
"address": "244 Columbus Place",
"employer": "Euron",
"email": "bradshawmckenzie@euron.com",
"city": "Hobucken",
"state": "CO"
}

検索のためのREST APIは_searchエンドポイントからアクセスできます。

$ curl -XGET 'localhost:9200/bank/_search?q=*&sort=account_number:asc&pretty&pretty'

q=*・・・bankインデックス内のすべてのdocumentにマッチするということ sort=account_number:asc・・・account_numberフィールドを使って検索結果をasc順にソートする

{
  "took" : 63,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1000,
    "max_score" : null,
    "hits" : [ {
      "_index" : "bank",
      "_type" : "account",
      "_id" : "0",
      "sort": [0],
      "_score" : null,
      "_source" : {
        "account_number":0,"balance":16623,"firstname":"Bradshaw","lastname":"Mckenzie","age":29,"gender":"F","address":"244 Columbus Place","employer":"Euron","email":"bradshawmckenzie@euron.com","city":"Hobucken","state":"CO"
      }
    }, 
    {   
      "_index" : "bank",
      "_type" : "account",
      "_id" : "1",
      "sort": [1],
      "_score" : null,
      "_source" : {
        "account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"
      }
    }, ...
    ]
  }
}

took・・・検索の実行時間(ms) timed_out・・・もし検索がタイムアウトしたら、true _shards・・・どれくらいの数のshardが検索されたかを表す hits・・・検索の結果 hits.total・・・検索にマッチしたdocumentの数 hits.hits・・・実際の検索結果の配列(デフォルトでは、はじめの10件) sort・・・結果のsortキー _score・・・指定した検索クエリにどれだけdocumentがマッチしているかを表す数値的指標。高ければ高いほど関連があるdocumentになる

上記と同じ検索をREST request APIで行う場合

$ curl -XGET 'localhost:9200/bank/_search?pretty' -H 'Content-Type: application/json' -d'
{
  "query": { "match_all": {} },
  "sort": [
    { "account_number": "asc" }
  ]
}'

Query Languageの紹介

詳しくはQuery DSLを参照。ここではいくつかの基本的な例を挙げる。

$ curl -XGET 'localhost:9200/bank/_search?pretty' -H 'Content-Type: application/json' -d'
{
  "query": { "match_all": {} }, #検索内容
  "from": 10,  #検索結果をどこから表示するか
  "size": 10,  #検索結果数の指定
  "sort": { "balance": { "order": "desc" } } #検索結果の順番
}'

Searchの実行

いくつかの基本的な検索パラメータを見ていく。

[_source] 検索結果に表示するfieldの指定。select account_number, blance from bank;のようなもの

$ curl -XGET 'localhost:9200/bank/_search?pretty' -H 'Content-Type: application/json' -d'
{
  "query": { "match_all": {} },
  "_source": ["account_number", "balance"]
}'

[matchクエリ] 特定のfieldを検索

$ curl -XGET 'localhost:9200/bank/_search?pretty' -H 'Content-Type: application/json' -d'
{
  "query": { "match": { "account_number": 20 } } #account numberが20のデータを返す
}'

$ curl -XGET 'localhost:9200/bank/_search?pretty' -H 'Content-Type: application/json' -d'
{
  "query": { "match": { "address": "mill" } } #addressフィールドに"mill"を含むデータを返す
}'

$ curl -XGET 'localhost:9200/bank/_search?pretty' -H 'Content-Type: application/json' -d'
{
  "query": { "match": { "address": "mill lane" } } #addressフィールに"mill"もしくは"lane"を含むデータを返す
}'

$ curl -XGET 'localhost:9200/bank/_search?pretty' -H 'Content-Type: application/json' -d'
{
  "query": { "match_phrase": { "address": "mill lane" } } #addressフィールドに"mill lane"を含むデータを返す
}'

[boolクエリ] addressフィールドに"mill"と"lane"が含まれているデータを返す

$ curl -XGET 'localhost:9200/bank/_search?pretty' -H 'Content-Type: application/json' -d'
{
  "query": {
    "bool": {
      "must": [
  { "match": { "address": "mill" } },
  { "match": { "address": "lane" } }
]
    }
  }
}'

addressフィールドに"mill"か"lone"が含まれているデータを返す

$ curl -XGET 'localhost:9200/bank/_search?pretty' -H 'Content-Type: application/json' -d'
{
  "query": {
    "bool": {
      "should": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}'

addressフィールドに"mill"と"lane"を含まないデータを返す

$ curl -XGET 'localhost:9200/bank/_search?pretty' -H 'Content-Type: application/json' -d'
{
  "query": {
    "bool": {
      "must_not": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}'

Filterの実行

すべてのデータの中から("must": {"match_all": {}})blanceフィールドの値が2000以上で3000以下のデータを返す

$ curl -XGET 'localhost:9200/bank/_search?pretty' -H 'Content-Type: application/json' -d'
{
  "query": {
    "bool": {
      "must": { "match_all": {} },
  "filter": {
    "range": {
      "balance": {
        "gte": 20000,
        "lte": 30000
      }
    }
  }
    }
  }
}'

Aggregationの実行

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment