初心者のためのRest APIから覚えるElasticsearch 

この記事は [Elasticsearch Advent Calendar 2015](http://qiita.com/advent-calendar/2015/elasticsearch) の5日目の記事です。

記事更新遅くなってしまい、申し訳ないです。。

# はじめに
みなさんはElasticserchのデータを確認したり、解析したりするために何を使っているのでしょうか？
[Elasticsearch Head](https://mobz.github.io/elasticsearch-head/)や、[kibana](https://www.elastic.co/products/kibana)など色々あるのですが、別々の環境にある複数のElasticsearchを扱うことがある時や開発段階の探り探りの状態ではやはり何よりも`REST API`を直接叩けるとかなり捗ります。

僕自体現在Elasticsearch歴2ヶ月で上記の環境だったため、
今のところ[POSTMAN](https://www.getpostman.com/)が最強のElasticsearchクライアントです。

2016/06/17 追記
※ 最強は[Sense](https://www.elastic.co/guide/en/sense/current/introduction.html)でした

という訳で僕がよく使うAPI一覧をまとめました。

参考 [公式API一覧](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html)
    
#### バージョン情報
Elasticsearch 1.5.2

## 1. Elasticserchのヘルスチェック
まずElasticsearchを導入後まずやることは、Elasticsearchを立ち上げることだと思います。（当たり前ですが）
起動状況・バージョンの確認などを行えます。

```:
$ curl -XGET 'localhost:9200/'
```

## 2.マッピング
データ構造（MYSQLでいうとDB,テーブル）の作成を行います。
開発段階でIndexをつくって、潰してを繰り返していたので、このAPIは何度も叩きました。

mappingsの中に作りたいType（テーブル）、Fields(カラム)を指定します。
簡単な一例のみ書いていますが、ただIndexを作るのみなら`settings`は不要です。

```
$ curl -XPOST 'localhost:9200/[index]?pretty' -d ' 
{
    "settings": {
        "index": {
            "creation_date": "1445580000000",
            "uuid": "xxxxxxxxxxxxxxxxxxxxxx",
            "number_of_replicas": "1",
            "number_of_shards": "5",
            "version": {
                "created": "1050299"
            }
        }
    },
    "mappings": {
        "[type]": {
            "properties": {
                "id": {
                    "type": "long"
                },
                "last_name": {
                    "type": "string"
                },
                "first_name": {
                    "type": "string"
                },
                "created_at": {
                    "format": "dateOptionalTime",
                    "type": "date"
                }
                "updated_at": {
                    "format": "dateOptionalTime",
                    "type": "date"
                }
            }
        }
    }
}'
```

各shard内のIndexの状況などを返してくれます。
以下のAPIでマッピングの結果確認を行います。

```
$ curl -XGET 'localhost:9200/[index]'
```

Indexの詳細なステータスチェックを行う場合はURL末尾に`_status` をつけます。

```
$ curl -XGET 'localhost:9200/[index]/_status'
```

間違えた場合、変更のあった場合などは一旦構成を作りなおすのに以下のAPIで削除します。

```
$ curl -XDELETE 'localhost:9200/[index]
```

## 3.ドキュメントを操作する

### ドキュメント作成
マッピングを行ったら、次に指定したテーブルへのデータをインサートします。
idを指定しない場合は適当な値が設定されます。

```
$ curl -XPOST 'localhost:9200/[index]/[type]/[id]?pretty' -d '
{
    "last_name":"のび",
    "first_name":"のびた",
    "height":150,
    "weight":40,
    "created_at":1406038,
}'
```

bulkインサートの場合は最後に`_bulk`をつけます。

```
$ curl -XPOST 'localhost:9200/[index]/[type]/_bulk?pretty' -d '
{ "index" : {}       }
{ "last_name"  : "のはら", "first_name": "ひろし", "age":35, "height":180.0 }
{ "index" : {}       }
{ "last_name"  : "のはら", "first_name": "みさえ", "age":29, "height":160.2 }
{ "index" : {}       }
{ "last_name"  : "のはら", "first_name": "しんのすけ", "age":5, "height": 105.9 }
'
```

ドキュメントのアップデートはTypeとレコードのIDを指定します。

```
$ curl -XPUT 'localhost:9200/[index]/[type]/[id]?pretty' -d '
{
    "first_name":"ひまわり",
    "updated_at":14000000
}'
```

ドキュメントの削除

```
$ curl -XDELETE 'localhost:9200/[index]/[type]/[id]' 
```

やっとデータを作成出来ました。



## 4.検索
作成したデータを検索します。
default_operatorに指定でAnd検索・or検索を切り替えられます。
`filelds`は複数指定可で、`_all` で全filedを対象にできます。

```
$ curl -XGET 'localhost:9200/[index]/[type]/_search?pretty' -d '
{
  "query" : {
    "simple_query_string" : {
      "query": "みなもと ほねかわ",
      "fields": ["last_name"],
      "default_operator": "or"
    }
  }
}'
```

ドキュメントを整列させて検索する場合はjsonに`sort`を追加し、ソートしたい配列を追加します。

```
$ curl -XGET 'localhost:9200/[index]/[type]/_search?pretty' -d '
{
  "query" : {
    "simple_query_string" : {
      "query": "まるこ さきこ",
      "fields": ["first_name"],
      "default_operator": "or"
    }
  },
  "sort" : [{ "created_at" : {"order" : "desc", "missing" : "_last"}}]
}'
```

## 5.更に検索する

普通の検索に特殊な条件を追加する場合は`function_score`を使用します。
検索条件毎に検索スコアの重み付けをしたり,フィールドから算出した値でスコアをつけたり等々ができ僕がElasticsearchを使い初めて一番テンションの上がった部分でした！（まだ全く使いこなせていませんが、、）
[function score query](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html)

簡単な条件文などもかけるので、例えば身長、体重からbmi値を計算して肥満判定の場合は検索スコアから1引く場合など以下の様になります。

```:
$ curl -XGET 'localhost:9200/[index]/[type]/_search?pretty' -d '
{
  "query" : {
    "function_score" : {
      "query" : {
        "simple_query_string" : {
          "query": "どらえもん Qたろう ころすけ",
          "fields": ["first_name"],
          "default_operator": "or"
        }
      },
      "boost_mode": "replace",
      "script_score" : {
          "script" : "weight = doc['weight'].value; height = doc['height'].value; bmi = weight / ((height)*(height)+1);if (bmi >= 25) return _score - 10 else return _score"
      }
    }
  }
}'
```

- fieldの値は `doc['field名'].value` で取得できる
- 改行を入れるとエラーになる
- script内の式によって値が0未満になった場合エラーになる
- 上記の例の場合`return`は無くても最後の値をうまいこととってくれるので不要。（僕は分かりやすくするためにいれています。）

#### function_scoreが動かない場合
初期設定のまま`function_score`クエリを使ってみたところエラーが帰ってきてしまい、jsonが間違えているのかと思って長いこと試行錯誤していたのですが、`function_score`を設定から有効にする必要があるようでした。

`elasticsearch.yml`にスクリプトを有効化する設定を追記し、Elasticsearchを再起動します。

```elasticsearch.yml
script.groovy.sandbox.enabled: true
```

## RestAPIの共通オプション
ここまでAPIだけまとめてきましたが、ここでも使っている`?pretty`等レスポンスの値を見やすくするためや、レスポンス形式を指定できる共通オプションがあるので、こちらも使用すると確認しやすくなります。
https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html


# 終わりに
Elasticsearchまだまだ手探り状態なので、色々拙い部分あるかと思います。間違い等何かあればご教授いただけると嬉しいです。
早く使いこなして素敵なElasticsearchライフを送りたいです。