はじめに
俺も世の中のイケてるエンジニアみたいにビッグデータを可視化してドヤ顔したい!
…ので友人から教えてもらったelasticsearchとkibanaを
へっぽこエンジニアがローカル環境で動作させるまでのメモ
環境
- Windows 10 Home 1803
- elasticsearch 6.3.0
- kibana 6.3.0
- curl 7.61.0
今回テストに使用するデータ
各家庭や工場等の電力消費量を集めたデータセット
https://archive.ics.uci.edu/ml/datasets/ElectricityLoadDiagrams20112014
特徴
- データ取得期間: [2011/1/1, 2015/1/1]
- 測定欠測値は存在しない
- 期間中に利用開始・終了がある場合、測定値は0と表示される
データ形式
- CSV形式
- カラム区切り文字: semicolon (;)
- 小数点区切り文字: colon (,) (ポルトガルではこれが標準らしい)
- 1番目のカラム: データ取得時間 (15分間隔)
- 2番目のカラムから: 消費電力 (kW単位)
インストール
Java
elasticsearchはJava製なのでJREのインストール
java version "1.8.0_171"
Java(TM) SE Runtime Environment (build 1.8.0_171-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)
設定してなければJAVA_HOMEを環境変数に設定
C:\Program Files\Java\jre1.8.0_171(インストールした場所を指定)
elasticsearchとkibana
elasticsearch
https://www.elastic.co/downloads/elasticsearch
windows環境なのでzipを選択
kibana
https://www.elastic.co/downloads/kibana
windowsのリンクをクリックしてzipをダウンロード
起動
- elasticsearchは以下のバッチファイルを起動
elasticsearch-6.3.0\bin\elasticsearch.bat
- kibanaは以下のバッチファイルを起動
kibana-6.3.0-windows\bin\kibana
今回は以下のようなバッチファイルを作成して1つにまとめる
start elasticsearch-6.3.0\bin\elasticsearch
start kibana-6.3.0-windows\bin\kibana
起動しているか確認
- elasticsearch
http://localhost:9200/
以上のURLにアクセスしてversion情報とかが入ったJSONが出力されればOK - kibana
http://localhost:5601/
以上のURLにアクセスして画面が表示されればOK
curl
今回はすでに入っていたものを使用(買ったばっかのWindows機なのになんで?)
curl 7.55.1 (Windows) libcurl/7.55.1 WinSSL
Release-Date: [unreleased]
Protocols: dict file ftp ftps http https imap imaps pop3 pop3s smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile SSPI Kerberos SPNEGO NTLM SSL
データ挿入
index作成
まずはindexを作成(MySQLで言うところのデータベース)
?pretty
をつけると改行付きのjsonが帰ってくる
curl -XPUT "localhost:9200/electric_power?pretty"
indexが作られているか確認
curl -XGET "localhost:9200/_cat/indices?v"
json作成
elasticsearchのBulkAPIで読み込むには以下のようにデータを2行1組のjsonへ変換する
IDを指定しない場合は適当な一意のIDが付与される。
{ "index" : { "_index" : "(挿入したいindex)", "_type" : "(挿入したいtype)", "_id" : "(一意のid)" } }
{ (実データのjson) }
今回はpythonを使用してjsonに変換
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import csv
import json
PATH = './dataset.txt'
JSON_BASE_NAME = './dataset'
def main():
with open(PATH, mode='r', encoding='utf-8', newline='') as f:
dialect = csv.Sniffer().sniff(f.readline(), delimiters=';')
f.seek(0)
reader = csv.reader(f, dialect)
header = reader.__next__()
header[0] = "datetime"
file_num = 0
writer = open(JSON_BASE_NAME + '_' + str(file_num) + '.json', mode='w', encoding='utf-8')
line_num = 0
for line in reader:
line_num = line_num + 1
writer.writelines(json.dumps({'index': {'_index': 'electric_power', '_type': 'portugal'}}))
writer.writelines('\n')
line_dict = make_line_dict(header, line)
writer.writelines(json.dumps(line_dict))
writer.writelines('\n')
# でかいのでファイル分割
if line_num >= 1000:
line_num = 0
file_num = file_num + 1
writer.close()
writer = open(JSON_BASE_NAME + '_' + str(file_num) + '.json', mode='w', encoding='utf-8')
writer.writelines('\n')
writer.close()
def make_line_dict(header, line):
line = list(map(lambda l: l.replace(',', '.'), line))
line[1:] = list(map(lambda val: float(val), line[1:]))
line_dict = dict(zip(header, line))
return line_dict
if __name__ == '__main__':
main()
elasticsearchに投入
変換したjsonをBulkAPIで投入。(データが大きすぎてcurlが動かなかったので分割)
ちなみにElasticsearch6系からContent-Typeヘッダが必須のようです。
私はここでハマりました。 (半ギレ)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
# ファイルの個数
FILE_NUM = 141
def main():
for i in range(FILE_NUM):
cmd = 'curl --noproxy localhost -H "Content-Type: application/json" ' \
'-XPUT localhost:9200/_bulk --data-binary @dataset_' + str(i) + '.json'
print(cmd)
os.system(cmd)
if __name__ == '__main__':
main()
以下にアクセスすると入れたデータが確認できる。
http://localhost:9200/electric_power/_search?pretty
データ可視化
データはelasticsearchに入れたので表示ができるはず
http://localhost:5601/ にアクセスするとkibanaのホーム画面が表示されるので
左側メニューの visualize
メニューをクリックして
index patternに electric_power
と入力し Next Step
ボタンを押せば
なんかグラフができるはず
…と思っていたがなんかうまく行かない。 (キレそう)
マッピングの確認
elasticsearchは何もしなくてもフィールドの型を定義してくれるらしいので
以下のURLにアクセスして、デフォルトの型を確認する。
http://localhost:9200/electric_power/_mapping?pretty
~ 略 ~
"datetime" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
~ 略 ~
どうも、デフォルトだと時刻フィールドがtextとして扱われているのが原因のよう
マッピングの変更
時刻として扱って欲しいので、自動生成されたマッピングのdatetimeの定義を以下のように修正
{
"mappings" : {
"portugal" : {
"properties" : {
"MT_001" : {
"type" : "float"
},
"MT_002" : {
"type" : "float"
},
~ 略 ~
"datetime" : {
"type" : "date",
"format" : "YYYY-MM-dd HH:mm:ss"
}
}
}
}
}
以下のコマンドで定義したマッピングを登録
curl -XDELETE "localhost:9200/*"
curl -H "Content-Type: application/json" -XPUT localhost:9200/electric_power --data-binary @mapping.json
再びアクセスして意図した定義になっているか確認
http://localhost:9200/electric_power/_mapping?pretty
今度こそデータの可視化
もう一度データをelasticsearchへ投入
http://localhost:5601/ にアクセスするとkibanaのホーム画面が表示されるので
左側メニューの Discover
メニューをクリックして
index pattern
に electric_power
と入力し
Time Filter field name
に datetime
を選択して Next Step
ボタンをクリック
再び Discover
メニューをクリックで…
やった~~~~
おわり
- とりあえず可視化はできたので一旦終わり
- どんなグラフがあるかはまたあとで覚える
おまけ
-
indexを削除するときはDELETEすればOK
curl -XDELETE "localhost:9200/*"
-
proxyサーバーがある環境の場合は
--noproxy localhost
で動作するかも
参考
以下の記事を見ながら作業してました。記事ありがとう!
https://qiita.com/kws9/items/7695262be0befb94897f
https://qiita.com/hiyuzawa/items/bad1a7e29fc8d1820bea