スキップしてメイン コンテンツに移動

Elasticsearch+Kibana のインストール、設定、使い方

簡単な説明

Elasticsearch

RDB のようにデータを溜め込むプログラム。
RDB と違い JSON を POST するだけでデータを溜め込んでくれる。
RDB のように事前にテーブル設計する必要もなく、自動で POST した JSON の各プロパティの型も推定してくれる。
事前に型を定義することもでき、実運用上ではそうした方がよい。
リッチなクライアントはないので、curl などを用いて REST API 経由でデータを操作する。
実際問題として、curl は面倒臭いので、Kibana に Elasticsearch の REST API を操作するための画面(Management/Dev Tools)があるので、それを利用すると便利。
本記事では Elasticsearch 8.17.4 を前提にしている。

Kibana

Elasticsearch にあるデータを可視化するツール。

ダウンロード

インストール

解凍して適当な場所に置くだけで良い(Windows/Linux/Mac どれも同じ)
実行に必要な Java もバンドルされているため、インストール不要。

設定

Elasticsearch

config/elasticsearch.yml の設定を以下のように変更する。
xpack.security.enabled: true

xpack.security.enabled: false

開発環境では X-Pack Security は不要なので、切ってよい。
これを設定しておかないと、http://localhost:9200 にアクセスしても何も表示されず、以下のようなログが表示される。

[2025-04-14T18:40:10,635][WARN ][o.e.h.n.Netty4HttpServerTransport] [desktop.local] received plaintext http traffic on an https channel, closing connection Netty4HttpChannel{localAddress=/[0:0:0:0:0:0:0:1]:9200, remoteAddress=/[0:0:0:0:0:0:0:1]:51896}

Kibana

設定変更は不要。

他の PC からもアクセスできるようにしたい場合

Elasticsearch

config/elasticsearch.yml
#network.host: 192.168.0.1

network.host: 192.168.0.1

Kibana

config/kibana.yml
#server.host: "localhost"

server.host: "192.168.0.1"

に変更する(192.168.0.1 は実際の IP アドレスに変更すること、Windows では ipconfig, Linux/Mac では ifconfig で確認できる)

プラグイン

どうせ後で使うことになるので、kuromoji を前もってインストールしておく。

bin/elasticsearch-plugin install analysis-kuromoji
bin/elasticsearch-plugin install analysis-icu

起動

Elasticsearch

bin/elasticsearch

Kibana

bin/kibana

起動確認

Elasticsearch

http://localhost:9200
JSON が表示されれば OK。

Kibana

http://localhost:5601
Kibana の画面が表示されれば OK。

network.hostserver.host の設定を変更している場合、localhost ではなく IP アドレスにすること。

Elasticsearch へのデータの投入

POST /テーブル名/_doc
{
  json データ...
}

のようにする。事前準備は不要。
テーブル名のことを Elasticsearch ではインデックスと呼ぶ。

例:

POST /diary/_doc
{
  "hiduke": "2025-04-01T01:23:45+09:00",
  "nikki": "今日は絶好調だった"
}
POST /diary/_doc
{
  "hiduke": "2025-04-02T23:45:01+09:00",
  "nikki": "今日は絶不調だった"
}

ここでは diary という名前でインデックスを作成している。JSON の中身はなんでもよい。
hidukenikki などといったプロパティが存在しなければならない、ということはない。
上記の例は RDB でいうプライマリキーを自動で採番している。手動がよい場合次のようにする。

POST /diary/_doc/1
{
  "hiduke": "2025-04-01T01:23:45+09:00",
  "nikki": "今日は絶好調だった"
}
POST /diary/_doc/2
{
  "hiduke": "2025-04-02T23:45:01+09:00",
  "nikki": "今日は絶不調だった"
}

Elasticsearch ではインデックスを日時で分ける運用をすることが多い(BigQuery でいうパーティション)。

POST /diary-2025.04.01/_doc/1
{
  "hiduke": "2025-04-01T01:23:45+09:00",
  "nikki": "今日は絶好調だった"
}
POST /diary-2025.04.02/_doc/2
{
  "hiduke": "2025-04-02T23:45:01+09:00",
  "nikki": "今日は絶不調だった"
}

インデックス名はなんでもよいが、上記の例では diary-2025.04.01, diary-2025.04.02 という名前の二つのインデックスを作成したことになる。
インデックスの命名規則は特になく自由に決めてよいが、Logstash という有名なツールがデフォルトでインデックス名-yyyy-MM.dd という命名規則を採用しているため、これに倣っている。
Kibana には「diary-*」にマッチするインデックスのデータをすべて集計する、といった便利な機能がある(RDB でいう UNION)ため、このように日付ごとにパーティションしても使い勝手が悪くなることはない(集計対象のインデックス名に「diary」と指定するか、「diary-*」と指定するかだけの違いしかない)。

マッピング

投入したデータに基づき Elasticsearch が自動でプロパティの型を決定する(動的マッピング)が、実運用上ではあらかじめ指定しておいた方がよい。この型付けを(明示的)マッピングという。

PUT /diary
{
  "mappings": {
    "properties": {
      "hiduke": {
        "type": "date",
        "format": "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
      },
      "nikki": {
        "type": "text"
      }
    }
  }
}

hiduke プロパティに date 型、nikki プロパティに text 型を明示的に指定している。
Elasticsearch は Java 製なので、日付の format には Java のパターン文字を使う。
タイムゾーンの指定は特殊で、「+09:00」の「+」を除いた部分(つまり 09:00)が 5 文字なので、Z を 5 個並べる。
これにより diary というインデックスに上記のマッピングが適用される。

ところで、インデックスを diary-2025.04.01, diary-2025.04.02 のようにパーティションしている場合はどうすればよいだろうか。
同じマッピングを複数のインデックスに毎回 PUT して設定するのは面倒である。
この場合インデックステンプレートを用いる。

PUT /_index_template/diary
{
  "index_patterns": ["diary-*"],
  "template": {
    "mappings": {
      "properties": {
        "hiduke": {
          "type": "date",
          "format": "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
        },
        "nikki": {
          "type": "text"
        }
      }
    }
  }
}

diary-*」にマッチするすべてのインデックスにマッピングを適用できる。
PUT する際の URL /_index_template/diarydiary の部分は、任意の文字列を指定すればよい(なんでもよい)。

kuromoji

Kibana を触っていると、日記の文章を元に全文検索やタグクラウドの可視化などをしたくなるかもしれない。
この場合マッピングのついでに kuromoji の設定をすればよい(上記のマッピング設定用の JSON に settings プロパティを追加すればよい)。

diary インデックスのみに適用する場合は以下のようにする。

PUT /diary
{
  "settings": {
    "analysis": {
      "tokenizer": {
        "kuromoji_user_dict": {
          "type": "kuromoji_tokenizer",
          "mode": "normal"
        }
      },
      "analyzer": {
        "kuromoji_normalize": {                 
          "char_filter": [
            "icu_normalizer"                    
          ],
          "tokenizer": "kuromoji_user_dict",
          "filter": [
            "kuromoji_baseform",
            "kuromoji_part_of_speech",
            "cjk_width",
            "ja_stop",
            "kuromoji_stemmer",
            "lowercase"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "hiduke": {
        "type": "date",
        "format": "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
      },
      "nikki": {
        "type": "text",
        "fielddata": true,
        "analyzer": "kuromoji_normalize",
        "fields": {
          "raw": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

diary-* インデックスに適用する場合は以下のようにする。

PUT /_index_template/diary
{
  "index_patterns": ["diary-*"],
  "template": {
    "settings": {
      "analysis": {
        "tokenizer": {
          "kuromoji_user_dict": {
            "type": "kuromoji_tokenizer",
            "mode": "normal"
          }
        },
        "analyzer": {
          "kuromoji_normalize": {                 
            "char_filter": [
              "icu_normalizer"                    
            ],
            "tokenizer": "kuromoji_user_dict",
            "filter": [
              "kuromoji_baseform",
              "kuromoji_part_of_speech",
              "cjk_width",
              "ja_stop",
              "kuromoji_stemmer",
              "lowercase"
            ]
          }
        }
      }
    },
    "mappings": {
      "properties": {
        "hiduke": {
          "type": "date",
          "format": "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
        },
        "nikki": {
          "type": "text",
          "fielddata": true,
          "analyzer": "kuromoji_normalize",
          "fields": {
            "raw": {
              "type": "keyword"
            }
          }
        }
      }
    }
  }
}

nikki プロパティの Aggregation を有効化するため fielddatatrue にしている。
analyzertemplate.settings.analysis.analyzertemplate.settings.analysis.tokenizer の設定を適用した kuromoji_normalize を指定する。
fieldsraw を定義することで、nikki.raw という名前で keyword 型としても利用できるようにしている。

Elasticsearch のデータをすべて削除してやりなおしたい

PUT /_cluster/settings
{
  "transient": {
    "action.destructive_requires_name": false
  }
}
DELETE /*

ワイルドカード(/*, /_all)を指定した DELETEaction.destructive_requires_namefalse に指定しないと動作しない(illegal_argument_exception, Wildcard expressions or all indices are not allowed)ため、最初に設定を変更する必要がある。

コメント