前書き
APIに勉強がてらElasticsearchを導入してみたいなと考え、まずElasticsearch勉強しようと思うも
Elasticearchに関する超初心者用の日本語ドキュメントはかなり少なそうで..。
やはり上記の公式ドキュメントは英語ですが分かりやすいので、ノート代わりにシンプルに内容をまとめます。
認識の違いがあったらごめんなさい。
セットアップ
■ Javaのバージョン確認
- 最低でもJava7以上である必要があります。
java -version
echo $JAVA_HOME
■ Download
- Unix環境を前提に
適当にディレクトリ移動して、下記コマンドでダウンロード
curl -L -O https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/tar/elasticsearch/2.4.1/elasticsearch-2.4.1.tar.gz
下記コマンドで解凍
tar -xvf elasticsearch-2.4.1.tar.gz
■ 起動
解凍したらelasticsearch-2.4.1
のようなディレクトリがあるはずなので、配下の./bin
に移動
cd elasticsearch-2.4.1/bin
下記のコマンドで起動します。
./elasticsearch
コマンド実行するとこんな感じで最終的にstarted
が表示されます。
[2016-09-30 11:05:37,078][INFO ][node ] [Paibo] started
基本操作
■ Index生成
curl -XPUT 'localhost:9200/customer'
- ポート番号はデフォルトで9200
- customerというIndexを作成(MySQLでいうところのdatebaseでしょうか)
-
?pretty
をつけるとレスポンスのJSONが整形されて出力されます
?pretty
なし
curl -XPUT 'localhost:9200/customer'
{"acknowledged":true}
?pretty
あり
curl -XPUT 'localhost:9200/customer?pretty'
{
"acknowledged" : true
}
Index確認
customerが追加されてます。
curl 'localhost:9200/_cat/indices?v'
health status index pri rep docs.count docs.deleted store.size pri.store.size
yellow open customer 5 1 0 0 260b 260b
■ Type生成
curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
{
"name": "John Doe"
}'
- externalというtypeを作成(MySQLでいうところのtableですね)
-
/1
でidを指定してレコード追加しています。
Response
{
"_index" : "customer",
"_type" : "external",
"_id" : "1",
"_version" : 1,
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"created" : true
}
type確認
id=1のtypeを確認します。
curl -XGET 'localhost:9200/customer/external/1?pretty'
Response
{
"_index" : "customer",
"_type" : "external",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"name" : "John Doe"
}
}
追加方法について
id=1で、{"name": "John Doe"}
を作成した後
curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
{
"name": "John Doe"
}'
{
"_index" : "customer",
"_type" : "external",
"_id" : "1",
"_version" : 1,
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"created" : true
}
id=1で、{"name": "Jane Doe"}
を生成しようとすると失敗します。
curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
{
"name": "Jane Doe"
}'
{
"_index" : "customer",
"_type" : "external",
"_id" : "1",
"_version" : 2,
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"created" : false
}
idを指定しないと、適当なidが付与されます。
curl -XPOST 'localhost:9200/customer/external?pretty' -d '
> {
> "name": "Jane Doe"
> }'
{
"_index" : "customer",
"_type" : "external",
"_id" : "AVd5vZRmkCj9N-SGg2rZ",
"_version" : 1,
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"created" : true
}
■ Index削除
curl -XDELETE 'localhost:9200/customer?pretty'
{
"acknowledged" : true
}
削除されていることを確認
curl 'localhost:9200/_cat/indices?v'
health status index pri rep docs.count docs.deleted store.size pri.store.size
customer
が消えています。
■ DocumentのUPDATE
Documentはレコードという認識でよさそうです。
このようにカラム"age"
を追加したような、UPDATEも可能です。
curl -XPOST 'localhost:9200/customer/external/1/_update?pretty' -d '
{
"doc": { "name": "Jane Doe", "age": 20 }
}'
{
"_index" : "customer",
"_type" : "external",
"_id" : "1",
"_version" : 3,
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
}
}
確認
curl -XGET 'localhost:9200/customer/external/1?pretty'
{
"_index" : "customer",
"_type" : "external",
"_id" : "1",
"_version" : 3,
"found" : true,
"_source" : {
"name" : "Jane Doe",
"age" : 20
}
}
■ DocumentのDELETE
id=1のDocumentを削除する例
curl -XDELETE 'localhost:9200/customer/external/1?pretty'
{
"found" : true,
"_index" : "customer",
"_type" : "external",
"_id" : "1",
"_version" : 4,
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
}
}
チュートリアル
準備
■ サンプルデータをダウンロード
上記URLより、サンプルデータをダウンロードした後「accounts.json」というファイルを展開。
accounts.json
下記のようなデータで構成されてます
{
"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"
}
■ Elasticsearchへ取り込み
「accounts.json」ファイルのあるディレクトリへ移動し、下記コマンドで取り込み
curl -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary "@accounts.json"
確認
curl 'localhost:9200/_cat/indices?v'
health status index pri rep docs.count docs.deleted store.size pri.store.size
yellow open bank 5 1 1000 0 447.2kb 447.2kb
-
bank
というIndexが作成されている。 -
docs.count
よりDocumentの数が1000であることが確認できる。
SearchAPI
■ クエリの種類
SearchAPIのクエリの発行方法は二種類
全件検索を例とすると、下記のようになる。
クエリ(1)
curl 'localhost:9200/bank/_search?q=*&pretty'
クエリ(2)
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": { "match_all": {} }
}'
■ JSON使用例
size
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": { "match_all": {} },
"size": 1
}'
-
"size":
で検索結果の件数を指定可能。例では1件。 - デフォルトは10
from
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": { "match_all": {} },
"from": 10,
"size": 10
}'
-
"from":
で検索開始位置の指定が可能。 - 開始番号が0なので、例では11番目から10件となる。
- デフォルトは 0。
sort
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": { "match_all": {} },
"sort": { "account_number": { "order": "desc" } }
}'
- 例では
"account_number"
のカラムを降順に10件表示となる。
_source
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": { "match_all": {} },
"_source": ["account_number", "balance"]
}'
- クエリの対象を指定する。
- 例では
"account_number"
と"balance"
が表示される。
■ queryの使用例
"account_number"が20
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": { "match": { "account_number": 20 } }
}'
"address"に"mill"が含まれる
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": { "match": { "address": "mill" } }
}'
"address"に"mill"または"lane"が含まれる
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": { "match": { "address": "mill lane" } }
}'
"address"に"mill lane"が含まれる
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": { "match_phrase": { "address": "mill lane" } }
}'
match⇒match_phraseにすることで、"mill lane"を含むものと指定できます。
■ Bool Query
must
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": {
"bool": {
"must": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}'
- "address"に"mill"と"lane"のどちらも含まれるDocumentが選択される。
should
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": {
"bool": {
"should": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}'
- "address"に"mill"もしくは"lane"の含まれるDocumentが選択される。
must_not
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": {
"bool": {
"must_not": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}'
- "address"に"mill"と"lane"どちらも含まないDocumentが選択される。
mustとmust_notの組み合わせ
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": {
"bool": {
"must": [
{ "match": { "age": "40" } }
],
"must_not": [
{ "match": { "gender": "M" } }
]
}
}
}'
- "age"が"40"であるが"gender"が"M"ではないDocumentが選択される。
filter
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": {
"bool": {
"must": { "match_all": {} },
"filter": {
"range": {
"balance": {
"gte": 20000,
"lte": 30000
}
}
}
}
}
}'
- 文字通り検索結果にfilterが可能
- 例の場合全件検索結果に、"balance"が20000以上、300000以下というfilterをかけてDocumentが選択される。
range | 意味 |
---|---|
gte | Greater-than or equal to |
gt | Greater-than |
lte | Less-than or equal to |
lt | Less-than |
■Aggregations(グループ的な意味)
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state"
}
}
}
}'
-
"size": 0
としているのは検索結果の表示は必要ではないため。 -
"terms":
はGROUP BYを意味します。 -
"field":"state"
でGROUP BYとしてます - GROUP BYされた
"state"
とその件数を、件数の降順に表示します - SQLで表すと下記のようになる。
SELECT state, COUNT(*) FROM bank GROUP BY state ORDER BY COUNT(*) DESC
range | 意味 |
---|---|
min | 最小値 |
max | 最大値 |
sum | 合計 |
avg | 平均値 |
terms | GROUP BY |
range | 範囲指定でGROUP BY |
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"size": 0,
"aggs": {
"group_by_age": {
"range": {
"field": "age",
"ranges": [
{
"from": 20,
"to": 30
},
{
"from": 30,
"to": 40
},
{
"from": 40,
"to": 50
}
]
},
"aggs": {
"group_by_gender": {
"terms": {
"field": "gender"
},
"aggs": {
"average_balance": {
"avg": {
"field": "balance"
}
}
}
}
}
}
}
}'
-
"range":
で"field": "age"
が[20-30,30-40,40-50]という条件でGROUP BY。 -
"terms":
で"field": "gender"
をさらにGROUP BY。 -
"avg":
でGROUP BYの結果から"field": "balance"
のavg(平均値)を出力