Edited at

Elasticsearch 超入門

More than 1 year has passed since last update.


前書き

APIに勉強がてらElasticsearchを導入してみたいなと考え、まずElasticsearch勉強しようと思うも

Elasticearchに関する超初心者用の日本語ドキュメントはかなり少なそうで..。

https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html

やはり上記の公式ドキュメントは英語ですが分かりやすいので、ノート代わりにシンプルに内容をまとめます。

認識の違いがあったらごめんなさい。


セットアップ


■ 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
}
}

 


チュートリアル

 


準備

 


■ サンプルデータをダウンロード

https://github.com/bly2k/files/blob/master/accounts.zip?raw=true

上記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(平均値)を出力