簡単な説明
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.host
や server.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 の中身はなんでもよい。
hiduke
や nikki
などといったプロパティが存在しなければならない、ということはない。
上記の例は 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/diary
の diary
の部分は、任意の文字列を指定すればよい(なんでもよい)。
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
を有効化するため fielddata
を true
にしている。
analyzer
に template.settings.analysis.analyzer
と template.settings.analysis.tokenizer
の設定を適用した kuromoji_normalize
を指定する。
fields
に raw
を定義することで、nikki.raw
という名前で keyword
型としても利用できるようにしている。
Elasticsearch のデータをすべて削除してやりなおしたい
PUT /_cluster/settings
{
"transient": {
"action.destructive_requires_name": false
}
}
DELETE /*
ワイルドカード(/*
, /_all
)を指定した DELETE
は action.destructive_requires_name
を false
に指定しないと動作しない(illegal_argument_exception, Wildcard expressions or all indices are not allowed)ため、最初に設定を変更する必要がある。
コメント
コメントを投稿