elasticsearch 基本コマンド編

##基本のREST API
###インデックスの作成
```json
PUT /INDEX
{
  "settings": {
    "number_of_shards": 2,
    "number_of_replicas": 2
  }
}
```
number_of_shards: シャードの数を指定
number_of_replicas: レプリカシャードの数を指定

###インデックスの削除
```json
DELETE /INDEX
```

###ドキュメントの追加
```json
POST /INDEX/_doc
{
  "name": "coffee",
  "price": 100,
  "in_stock": 10
}

レスポンス
{
  "_index" : "products",
  "_type" : "_doc",
  "_id" : "dKQQz3IBimm59hFUskBJ", 
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 3,
    "successful" : 1, 
    "failed" : 0 
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}
```
"__id" : ドキュメントのID、指定しない場合は自動で付与される
"_shards" : シャードをどうしたかの結果
ドキュメントを追加するという意味で_docを使用する
シャードは現在１つしか設定していない

###ドキュメントの追加(IDを指定)
```json
API  index/_type/_id
POST /products/_doc/100
{
  "name": "toaster",
  "price": 111,
  "in_stock": 110
}
```
※クラスターの設定でaction.auto_create_indexという項目をtrueにしておくと
作成していないindexにドキュメントを追加しようとした場合、自動でインデックスが作成される。

###ドキュメントの取得
```json
API /index/_type/_id
GET /product/_doc/100

レスポンス
{
  "_index" : "products",
  "_type" : "_doc",
  "_id" : "100",
  "_version" : 2,
  "_seq_no" : 2,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "toaster",
    "price" : 111,
    "in_stock" : 110
  }
}
```
ドキュメント追加時に指定したjsonは"_source"の中に記述され返ってきます。
"found" : 指定したIDのドキュメントが見つかった場合はtrueとなる。

###ドキュメントの更新
```json
API /index/_update/_id
POST /products/_update/100
{
  "doc": {
    "in_stock": 20,
    "tags": ["electronics"]
  }
}

レスポンス
{
  "_index" : "products",
  "_type" : "_doc",
  "_id" : "100",
  "_version" : 3,
  "result" : "updated",
  "_shards" : {
    "total" : 3,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 3,
  "_primary_term" : 1
}

確認
GET /products/_doc/100
{
  "_index" : "products",
  "_type" : "_doc",
  "_id" : "100",
  "_version" : 4,
  "_seq_no" : 4,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "toaster",
    "price" : 111,
    "in_stock" : 20,
    "tags" : [
      "electronics"
    ]
  }
}
```
"in_stock": 既存の項目を更新
"tags": 新規に項目を追加
"doc": この中に更新する値を入力する
"result": updatedとなっているので成功、noopは失敗

###更新スクリプトを実行
```json
API /index/_update/_id
POST /products/_update/100
{
  "script":{
    "source": "ctx._source.in_stock++"
  }
}
```
ctx: コンテキストであり、ソースドキュメントにアクセスする。
今回はin_stockの数をプラス１している。
”ctx._source.in_stock = 10"のように割り当てもできる。

###更新スクリプトを実行(パラメータ付与)
```json
API /index/_update/_id
POST /products/_update/100
{
  "script":{
    "source": "ctx._source.in_stock -= params.num",
    "params": {
      "num": 4
    }
  }
}
```
"params"の中にパラメータをキーとバリューで設定し使用する時はparamsオブジェクトにアクセスして使用する。

###ドキュメントの更新(アップサートを使用)
```json
POST /products/_update/101
{
  "script":{
    "source": "ctx._source.in_stock++"
    },
  "upsert":{
    "name": "blender",
    "in_stock": 8
  }
}
``
アップサートとは条件に応じてドキュメントを更新するか挿入するかにもとずいて更新すること。
ドキュメントがない場合は"upsert"の中身が設定される。

###ドキュメントの置き換え
```json
現在
{
  "_index" : "products",
  "_type" : "_doc",
  "_id" : "100",
  "_version" : 8,
  "_seq_no" : 8,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "toaster",
    "price" : 111,
    "in_stock" : 17,
    "tags" : [
      "electronics"
    ]
  }
}

置き換え
POST /products/_doc/100
{
  "name": "toaster",
  "price": 111,
  "in_stock": 110
}

結果
{
  "_index" : "products",
  "_type" : "_doc",
  "_id" : "100",
  "_version" : 9,
  "_seq_no" : 10,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "toaster",
    "price" : 111,
    "in_stock" : 110
  }
}
```
"tags"フィールドがなくなっている。

###ドキュメントの削除
```json
API /index/_type/_id
DELETE /products/_doc/101
```

###同時実行制御
```json
GET /products/_doc/100

レスポンス
{
  "_index" : "products",
  "_type" : "_doc",
  "_id" : "100",
  "_version" : 9,
  "_seq_no" : 10,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "toaster",
    "price" : 111,
    "in_stock" : 110
  }
}

POST /products/_doc/100?if_primary_term=1&if_seq_no=10
{
  "doc":{
    "in_stock": 123
  }
}

レスポンス
{
  "_index" : "products",
  "_type" : "_doc",
  "_id" : "100",
  "_version" : 10,
  "result" : "updated",
  "_shards" : {
    "total" : 3,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 12,
  "_primary_term" : 1
}

同じコマンドで２回目実行
POST /products/_doc/100?if_primary_term=1&if_seq_no=10
{
  "doc":{
    "in_stock": 123
  }
}

レスポンス
{
  "error": {
    "root_cause": [
      {
        "type": "version_conflict_engine_exception",
        "reason": "[100]: version conflict, required seqNo [10], primary term [1]. current document has seqNo [12] and primary term [1]",
        "index_uuid": "PfBK8jn7Sa-tsv_OmUfHRg",
        "shard": "0",
(以下省略)
```
primary_termとseq_noを指定しアップデートを行う。seq_noは毎回更新されるので
同じドキュメントを同時に更新される可能性がある場合やスレッドを利用している場合などに
使用することができる。

###クエリでドキュメントを更新する
```json
POST /products/_update_by_query
{
  "script":{
    "source": "ctx._source.in_stock--"
  },
  "query":{
    "match_all": {}
  }
}
```

###クエリでドキュメントを削除する
```json
POST /products/_delete_by_query
{
  "query":{
    "match_all": {}
  }
}
```

##bulkとは
bulkとは多数のドキュメントを一気に追加や削除など操作する時に使用する

###bulk処理,index指定なし
```json
API /_bulk
POST /_bulk
{ "index": { "_index": "products" , "_id": 200}} ---①
{ "name": "espresso machine" , "price": 199 , "in_stock": 5} ---②
{ "create" : {"_index": "products" , "_id": 201}} ---③
{ "name": "milk_frother" , "price": 149 , "in_stock": 3} ---④
{ "update": { "_index": "products" , "_id": 200}}
{ "doc": { "price": 90}}
```
①、②はすでにあるインデックスproductsに対してidを200に指定し、その中に②のjsonをドキュメントとして追加している。
③、④はproductsというインデックスを作成し、idの201に④のjsonをドキュメントとして追加している。

###bulk処理、index指定
```json
POST /produts/_bulk
{ "update": { "_id": 200}}
{ "doc": { "price": 21 }}
```
###bulk処理、curlコマンド
```bash
$ curl -H "Content-Type: application/x-ndjson" -XPOST http://localhost:9200/products/_bulk --data-binary "@bulk.json"
$ cat bulk.json
{"index":{"_id":902}}
{"name":"Eggplant"}
{"index":{"_id":903}}
{"name":"Water Tap"}
....(以下省略)最後の行はテキストエディタで改行を入れないとエラーがでる場合がある。
```
--data-binaryに@を頭に付与してjsonファイルを指定する