sakutarou’s blog

とりあえずWeb系技術をゆるく書いていく

Elasticsearchドキュメント操作の基本

ドキュメントの登録

PUT

IDを指定して登録します。
IDに使える文字は半角英数っぽい

API形式

http://ホスト:9200/インデックス名/ドキュメントタイプ名/ID

例)

curl -XPUT http://localhost:9200/my_index/my_type/1 \
-H 'Content-Type: application/json' -d'
{
    "name": "kozo",
    "address": "japan",
    "message": "hello world"
}
'

POST

IDはランダムな英数で自動採番される。
他にPUTとの違いがあるのかな?

API形式

http://ホスト:9200/インデックス名/ドキュメントタイプ名/

例)

curl -XPOST http://localhost:9200/my_index/my_type \
-H 'Content-Type: application/json' -d'
{
    "name": "kozo",
    "address": "japan",
    "message": "hello world"
}
'

ドキュメントの取得

ID指定での取得方法です。

API形式

http://ホスト:9200/インデックス名/ドキュメントタイプ名/ID

例)

curl -XGET http://localhost:9200/my_index/my_type/1
curl -XGET http://localhost:9200/my_index/my_type/1?pretty
curl -XGET http://localhost:9200/my_index/my_type/1/_source?pretty
  • ?pretty を指定することでレスポンスを見やすくフォーマットしてくれます
  • _source を指定すると登録内容のみが取得できます

ドキュメントの検索

とりあえず完全一致

APII形式

http://ホスト:9200/インデックス名/ドキュメントタイプ名/_search

例)

curl -XGET http://localhost:9200/my_index/my_type/_search?pretty -H 'Content-Type: application/json' -d'
{
    "query" : {
        "match" : {
            "name": "kozo"
        }
    }
}'

検索範囲

# my_typeの中から検索
http://localhost:9200/my_index/my_type/_search?pretty
# my_indexの中から検索
http://localhost:9200/my_index/_search?pretty
# 複数indexの中から検索
http://localhost:9200/my_index,my_index2/_search?pretty
# ワイルドカード指定
http://localhost:9200/my_index*/_search?pretty
# 全体から検索
http://localhost:9200/_search?pretty

ドキュメントの全体更新

PUTでドキュメントの全体を更新します

API形式

http://ホスト:9200/インデックス名/ドキュメントタイプ名/ID

例)

curl -XPUT http://localhost:9200/my_index/my_type/1 \
-H 'Content-Type: application/json' -d'
{
    {
        "name": "kozo",
        "address": "japan",
        "message": "hello world"
    }
}
'

ドキュメントの一部更新

更新だけど、 POST を発行するみたい。
内部的には削除 => 再登録なのかな? doc を指定して送信します

API形式

http://ホスト:9200/インデックス名/ドキュメントタイプ名/ID/_update

例)

curl -XPOST 'http://192.168.10.11:9200/my_index/my_type/1/_update?pretty' -H 'Content-Type: application/json' -d'
{
    "doc": {
        "user_name": "kozo(update test)"
    }
}
'

ドキュメントの削除

ID指定で削除する

API形式

http://ホスト:9200/インデックス名/ドキュメントタイプ名/ID

例)

curl -XDELETE http://192.168.10.11:9200/my_index/my_type/1?pretty

インデックスの作成

インデクスを作成せずにドキュメントの登録を行うとElasticsearchが自動的にインデックスを作成している。
インデックスを明示的に作成する必要があるタイミングは以下ののような デフォルト値 でインデックスを作成したくない場合となる

  • レプリカ数を変更したい場合
  • シャード数を変更したい場合(特にシャード数はインデックス作成時のみにしか変更することは出来ない)

API形式

http://ホスト:9200/インデックス名

例)

curl -XPUT "http://192.168.10.11:9200/my_index3" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 2
  }
}'

例2) すべてを書略した場合

curl -XPUT "http://192.168.10.11:9200/my_index3"

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

API形式

http://ホスト:9200/インデックス名/_settings

例)

curl -XGET "http://192.168.10.11:9200/my_index3/_settings?pretty"

インデックス設定の更新

API形式

http://ホスト:9200/インデックス名/_settings

例)

curl -XPUT "http://192.168.10.11:9200/my_index3/_settings" -H 'Content-Type: application/json' -d'
{
  "index": {
    "number_of_replicas": 3
  }
}'

インデックスの削除

API形式

http://ホスト:9200/インデックス名

例)

curl -XDELETE "http://192.168.10.11:9200/my_index3"

Elasticsearchの用語

自分の備忘録的に書いておきます
徐々に増やす予定

インデックス

RDBでの DB に相当する。

ドキュメントタイプ

RDBでの テーブル に相当する
ドキュメントタイプの中に含まれるフィールドのデータ構造やデータ型を記述したものを マッピング と呼ぶ

ドキュメント

RBDでの 1レコード に相当する。
一般的なRDBとの違いは JSONオブジェクトを保存するところである。

IDはインデックスへのドキュメントを格納するタイミングで自動採番される。

フィールド

RDBでの カラム に相当する。
ElasticsearchのドキュメントはJSONになっているので、 フィールドは JSONの「キー:バリュー」の一組になる。

基本的にはフィールド単位ので検索となる。

型としては、 text, long, short, integer, float, date, boolean など基本的にそろっている

Node

サーバーとイコール?

Shard

1つのインデックスは複数のShardから構成されている?
Shardを増やすと基本的には性能があがる?

デフォルト値とことなるShard数を持つIndexを作成したい場合は明示的に作成する

Replica

Shardとの違いがあまり分かってない。

Elasticsearchの起動 (Docker)

Elasticsearchを今まで使ってこなかったのですが、必要に迫られて使うことに。
新しくて・基礎から丁寧に説明してある、いい書籍があったのでこれを読みながら頑張ってみます。

とりあえず起動

Dockerにimageがあったので起動してみようと思ったのですが3つimageが存在するようです。

一番上に Official Repository と書いてあったのでこれを使っていたのですがどうやら違うようです。
Descriptionに DEPRECATION NOTICE 書いてあった。。。。

ちゃんと英語読まなきゃね。。。

2つ目、3つ目は同じようですが、 3つめが公式サイトになるので、今回は3つ目を使用します。
実践ガイドの書籍も3つ目を使用しています。

こんどこそ起動

基本的には、公式に丁寧に書いてあります。

www.elastic.co

イメージを取ってきます

docker pull docker.elastic.co/elasticsearch/elasticsearch:6.3.1

イメージ名を変更する

公式サイトでは名前の変更をしてないので変更する必要はないのですが、このままだとイメージ名が長いので elasticsearch:6.3.1 に変更しちゃいます。

docker tag {取得したイメージID} elasticsearch:6.3.1

# 変更前は削除
docker rmi docker.elastic.co/elasticsearch/elasticsearch:6.3.1

起動

docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:6.3.1

動作確認

curl http://192.168.10.11:9200/_cat/health

# こんな値が帰ってくればOK!
> 1532148126 04:42:06 docker-cluster green 1 1 0 0 0 0 0 0 - 100.0%

これでとりあえず実行環境はそろいました。

WSL上でDockerが動いた!けどまだつらい?

ネットでWSL上でDockerが動くようになってたと見かけたのでTryしてみました。
結果はまだつらそうかな?

WSLのインストール + Ubuntuのインストール

ネットで調べたらいっぱい出てくるのでそちらで

注意点

  • Ubuntu自体を管理者で実行する(右クリック => 管理者として実行)

Dockerのインストール

これでインストール + 起動が出来たのですが、Docker CEでは動作しませんでした。
インストールされるバージョンも Docker version 1.13.1, build 092cba3 とちょっと古めです。

sudo apt update
sudo apt upgrade

# docker.ioを利用する
sudo apt install docker.io

sudo cgroupfs-mount

sudo usermod -aG docker $USER

sudo service docker start

hello-world

docker run hello-world

f:id:sakutarou:20180715024846p:plain

Apacheを動かしてみる

これも普通に動作します

docker run -p 8080:80 --name apache httpd:2.4.33-alpine

コンテナに入りたい。。。

コンテナにエラーが出て入れませんでした。
解決策あるのかな。。。

docker exec apache /bin/bash
rpc error: code = 13 desc = invalid header field value "oci runtime error: exec failed: container_linux.go:247: starting container process caused \"could not create session key: function not implemented\"\n"

まだ難しい?

安定運用可能になるまでには、もう少し時間がかかりそう?
普通に使えるようになると便利そうなんだけどな。。。

巷で噂のデータ可視化ツールMetabaseを試してみた

最近データの可視化にRedashを利用してます。
Redashより素晴らしいとの噂の Metabase を試してみました。

www.metabase.com

以下を参考にさせて頂きました

OSSのデータ可視化ツール「Metabase」が超使いやすい - Qiita
MetabaseがRedashの苦労を吹き飛ばすくらい熱い - Qiita

Metabaseのいいところ

  • Dashboardの自由度が高い
    • グラフのサイズを自由に変更できる
    • 特定データの内訳をドリルダウンすることが出来る
  • SQLを書かなくても、結構自由にグラフを作れる

とりあえずMetabase起動!

docker run -d -p 3000:3000 --name metabase metabase/metabase

とりあえず上記コマンドで起動可能です。
ただMetabaseにアクセスできるようになるには少し時間がかかります。
docker logs -f metabase で起動完了までしばらく待ちましょう。

Metabase Initialization COMPLETE と表示されれば準備完了です。
site URL が表示されるのでブラウザからアクセスして初期設定しましょう。

自分は下記のエラーが発生しました

metabase Error parsing liquibase.yaml

上記エラーが出た場合は、メモリ不足の可能性があるそうです。
ホストに割り当ててるメモリ量を 1G => 2Gに変更しました。

グラフを作る

Question がグラフ用のデータ作成になります。
[New Question]-[Custom or Native query] をクリックしてデータを作成します。

Dashboardを作る

作ったQuestionを適当に配置して、サイズを自由に決めます
サイズをドラッグで自由に決めれるのがいい!
Redashの場合、横幅が広いモニターだとどうしても、横長で間抜けなグラフが配置されていたのが、 Metabase だと自分の思った通りに配置できるのがいい!

f:id:sakutarou:20180108204605p:plain

作成したDashboardを共有する

初期状態ではDashboardを共有することは出来ません。
Admin Panel から共有設定を有効にする必要があります。

  1. [メニュー]-[Admin Panel]-[Public Sharing]で共有設定許可画面まで進む
  2. Enableにする
  3. Dashboardに行き、Sharing設定する

とりあえず、乗り換えてみよう

まだ少ししか触ってないけど乗り換えてみる!
かっこいい!
ただし、Metabaseのバージョンは 0.27.2 なので要注意!!!

f:id:sakutarou:20180108205930p:plain

要調査

現状コンテナを落とすとMetabaseのデータが消える
データの保存先を調べて、ホストをマウントするなどの検討が必要

GitHub Appsを作ってみたら色々詰まって苦労した。。。

開発合宿でGitHub Appsでアプリを初めて作ってみました
自分が詰まったところを中心に情報を残します

fusic.co.jp

GitHub 連携

GitHubで何かしら連携をやろうと考えた場合以下が考えられます。
上3つは今でも使ったことがあるのですが、GitHub Appsは全く使ったことがありませんでした。
なので今回は GitHub Apps にトライしてみました。

GitHub Appsって何?

特徴としては以下

  • organization単位にインストールすることが可能(個人アカウントで作成することも可能)
  • 特定のリポジトリのみにアクセス権を与えることが可能
  • 詳細な権限設定とWebhookが利用可能
  • JWT認証をすることでAPIコールも可能
  • 一般公開も可能(自分の組織に限定することも可能)

要は、OAuthなど今まで個人に紐づいていたものが組織に紐づいて、且つ WebhookとAPIコールもくっついてくるすっごい便利なものだよと

GitHub Appsの登録

とりあえず最初にAppsの登録をします。
ここで Webhookや権限などを設定しておきます。

Creating a GitHub App | GitHub Developer Guide

JWT認証

APIをコールする為には、JWT認証を行いトークンを取得する必要があります。
ここでがっつり詰まってしまいました。

どうすればいいの

このURLに対して証明書と一緒にPOSTを送信するだけ!
すっごい簡単!
※ :installation_id は自身のものに修正する
https://api.github.com/installations/:installation_id/access_tokens

つまりポイントその1

そもそも installation_id って何!

WebHookリクエストの一部としてくっついてきます。

  # 上省略
  "installation": {
    "id": XXXXXX
  }

これでPOSTが送信できる!

つまりポイントその2

何をPOSTすればいいのか分からない!
以下をPOSTします。

- "iat": 現在日時タイムスタンプ,
- "exp": 発行するJWTの失効日時タイムスタンプ(最大10分), 
- "iss": GitHub App's identifier

GitHub App's identifier 何これ!
こいつが何かわかりませんでした。。。

作成したGitHub AppsのGeneralページにある AboutのIDGitHub App's identifier になります。
Private key も 同じ場所にあります。

つまりポイント3

ヘッダーは以下を指定する

"Authorization": "Bearer 作成したJWT",
"Accept": "application/vnd.github.machine-man-preview+json"

何つくったの?

GitHub + Amazon API Gateway + AWS Lambda *+ PythonGitHubラベル管理アプリを作りました。
ソースコードを整理できたら公開するかも。。。

参考URL

https://qiita.com/icoxfog417/items/fe411b94b8e7ae229e3e

Authentication options for GitHub Apps | GitHub Developer Guide

Travis CIみたいなGitHub連携アプリってどうやって作るんだ

GitHubで使われている Travis CI のような連携アプリを作りたい!
と思いついたので、まずはステータスを切り替えれるようにするところまで進んでみる。
※セキュリティとか置いておいて、まずは必要最低限まで

f:id:sakutarou:20170219234506p:plain

アプリケーション作成

以下の順番でアプリケーション作成画面まで進む。
[GitHub] - [Settings] - [OAuth applications] - [Register a new application]

進めたらアプリケーション作成

f:id:sakutarou:20170219235408p:plain

f:id:sakutarou:20170219235422p:plain

callback URL Client ID Client Secret をメモっておきます。

OAuth認証

まず、GitHubにアクセス
Client ID には先ほどメモっておいたものを使います。

https://github.com/login/oauth/authorize?client_id={Client ID}&scope=repo:status

認証を行うと callback URL に設定したURLに code が戻ってきます。

http://example.com/oauths/callback?code={コード}

次に コード を利用して、アクセストークンを取得します。
取得した、 コード Client ID Client Secret を利用します。

https://github.com/login/oauth/access_token?code={コード}&client_id={Client ID}&client_secret={Client Secret}

GitHubステータス変更

以下のAPIを実行して対象プルリクエストの head => sha を取得する

https://api.github.com/repos/:owner/:repo/pulls

- :owner => GitHubユーザー
- :repo => リポジトリ

以下のURLに対して必要な情報をPOSTします。

https://api.github.com/repos/:owner/:repo/statuses/:sha

- :owner => githubユーザー
- :repo => リポジトリ名
- :sha => pullsで取得した sha

POST値

JSONで以下の内容をPOSTする

  • state : pending, success, error, failure のいづれか
  • target_url : 詳細ページへのリンク
  • description : 説明
  • context : 見出し

その他

アクセストークンの使い方

Authorization: token {アクセストークン} の形でヘッダーに組み込む

  or

?access_token={アクセストークン} の形でGET値のパラメーター組み込む

UserAgentが必須である

ヘッダーにユーザーエージェントとして、 アプリ名 を指定する

とりあえず、ここまで
次はhook処理