注目の記事

Elasticsearch 6 を利用する前に把握しておいた方がよさそうなこと

2017.09.26

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ども、藤本です。

現地時間 8/31 に Elastic Stack の次期メジャーバージョンの 6.0.0 Beta 2 がリリースされました。

Elastic Stack 6.0.0-beta2リリース

過去の Elasticsearch はメジャーバージョンバージョンアップ時に機能が変更となったり、非推奨になったり、廃止になったり、大きな変化を行ってきました。今回の 5系 → 6系に際しても大きな変化があるはずです。ということで Elasticsearch 6系の Breaking Changes に目を通してみました。今回は私が気になった項目をご紹介します。利用方法によって影響する項目は異なるので 6系をご利用される方は一通り目を通すことを推奨します。

Breaking Changes

バージョン 2系以前に作成されたインデックスは読み取れない

Elasticsearch 2系以前に作成したインデックスは Elasticsearch 6.x にアップデートすると読み取れません。現在、2系以前に作成したインデックスがある場合、5系で一度、reindex などでインデックスを再作成してから 5系 -> 6系へアップグレードする必要があります。

2.4.2 -> 5.6.1 -> 6.0.0-beta2 の流れで試してみました。

# yum install -y elasticsearch-2.4.2.rpm
:
Installed:
  elasticsearch.noarch 0:2.4.2-1

Complete!
# systemctl start elasticsearch
### インデックス作成
# curl -XPOST localhost:9200/index/type -d'{"version": "2.4.2"}'
{"_index":"index","_type":"type","_id":"AV62pXFYgIwLu6rooGEg","_version":1,"_shards":{"total":2,"successful":1,"failed":0},"created":true}

# yum update -y elasticsearch-5.6.1.rpm
:
Updated:
  elasticsearch.noarch 0:5.6.1-1

Complete!

# systemctl daemon-reload
# systemctl restart elasticsearch
### 5系にアップデートしても読み取れる
# curl localhost:9200/index/_search
{"took":115,"timed_out":false,"_shards":{"total":5,"successful":5,"skipped":0,"failed":0},"hits":{"total":1,"max_score":1.0,"hits":[{"_index":"index","_type":"type","_id":"AV62pXFYgIwLu6rooGEg","_score":1.0,"_source":{"version": "2.4.2"}}]}}

# yum update elasticsearch-6.0.0-beta2.rpm
:
Updated:
  elasticsearch.noarch 0:6.0.0_beta2-1

Complete!

# systemctl daemon-reload
# systemctl restart elasticsearch
### 6系にアップデートすると読み取れない
# curl localhost:9200/index/_search
{"error":{"root_cause":[{"type":"index_not_found_exception","reason":"no such index","resource.type":"index_or_alias","resource.id":"index","index_uuid":"_na_","index":"index"}],"type":"index_not_found_exception","reason":"no such index","resource.type":"index_or_alias","resource.id":"index","index_uuid":"_na_","index":"index"},"status":404}

### インデックスを認識していない
# curl localhost:9200/_cat/indices
yellow open .kibana Oko0IE85SLeTvpENoUyDtw 1 1 1 0 3.5kb 3.5kb

インデックス内の複数タイプ利用不可

Elasticsearch のデータの論理構造はインデックスの中にタイプがあり、タイプの中にドキュメントがあるという構成です。5系までは一つのインデックスに複数のタイプを定義することが可能でした。6系からは一つのインデックスに一つのタイプしか定義できなくなります。Elasticsearch のロードマップではタイプ自体を削除する方向で進んでいます。インデックスに複数タイプが登録できるメリットは多くありませんでした。逆にインデックスと、タイプの分割単位が分かりづらいという設計上に悩みが発生しました。
ただ一点、インデックス内に複数タイプを利用するシーンとして、Parent-Child タイプの利用があります。Elasticsearch は RDBMS のような DB 間、テーブル間でのデータの JOIN の機能を保持していません。類似する機能として、Elasticsearch では Parent-Child タイプという機能でデータ間を親子として紐付けることで JOIN のようなことができました。複数タイプが利用不可になることで Parent-Child タイプが利用できなくなります。その代わりにフィールドタイプに join タイプが追加され、これを利用することで Parent-Child と似たことができます。

Query DSL の変更

Query DSL で廃止になったものや、非推奨となったものが多くあります。アプリケーションで使っているものがないか一通りチェックすることを推奨します。個人的には{}(空の波括弧)が入っているとエラーになるのがちょっとマズイな。。

Content-Type の指定必須となります

Elasticsearch への API は Transport通信を除いて、HTTP(s) リクエストによって操作します。Elasticsearch 5系までは自動検出していた Content-Type ヘッダですが、Elasticsearch 6系より指定が必須となりました。

### Content-Type を指定しないとエラー
$ curl -XPOST localhost:9200/index/type -d '{
  "message": "test message"
}'
{"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}

### Content-Type に application/json が必要
$ curl -H "Content-Type: application/json" -XPOST localhost:9200/index/type -d '{
  "message": "test message"
}'
{"_index":"index","_type":"type","_id":"4oQbCV4B-cnsJtWgmPBM","_version":1,"result":"created","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":0,"_primary_term":1}

### Bulk API も application/json で実行可能だが、ドキュメントでは application/x-ndjson で指定
$ cat requests
{ "index" : { "_index" : "test", "_type" : "type1", "_id" : "1" } }
{ "field1" : "value1" }

$ curl -s -H "Content-Type: application/x-ndjson" -XPOST localhost:9200/_bulk --data-binary "@requests"
{"took":208,"errors":false,"items":[{"index":{"_index":"test","_type":"type1","_id":"1","_version":1,"result":"created","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":0,"_primary_term":1,"status":201}}]}

_allフィールドが利用不可となります

全てのフィールドのデータを含む_allフィールドが利用できなくなります。デフォルト無効かと思いきや、有効に設定してもエラーとなります。query_stringsimple_query_stringall_fieldsオプションにより全てのフィールドから検索することができます。

PUT all_field
{
  "mappings": {
    "type": {
      "_all": {
        "enabled": true
      }
    }
  }
}
{
  "error": {
    "root_cause": [
      {
        "type": "mapper_parsing_exception",
        "reason": "Failed to parse mapping [type]: Enabling [_all] is disabled in 6.0. As a replacement, you can use [copy_to] on mapping fields to create your own catch all field."
      }
    ],
    "type": "mapper_parsing_exception",
    "reason": "Failed to parse mapping [type]: Enabling [_all] is disabled in 6.0. As a replacement, you can use [copy_to] on mapping fields to create your own catch all field.",
    "caused_by": {
      "type": "illegal_argument_exception",
      "reason": "Enabling [_all] is disabled in 6.0. As a replacement, you can use [copy_to] on mapping fields to create your own catch all field."
    }
  },
  "status": 400
}

Boolean type に指定可能な値がtrue/falseのみとなります

Elasticsearch 5系まで Boolean type のフィールドに 0/1、on/off、yes/no、true/false など多くの値を設定することが可能でしたが、Elasticsearch 6系からは true/false の指定のみとなりました。"true"/"false"(文字化)でも利用できます。

フィールドタイプにstringが指定できなくなります

Elasticsearch 5系から文字列を扱うフィールドタイプがstringからtextkeywordに変更しました。5系ではstringタイプは非推奨となり指定することができました。6系ではstringタイプを指定するとエラーになるように変更となりました。

PUT index
{
  "mappings": {
    "type": {
      "properties": {
        "name": {
          "type": "string"
        }
      }
    }
  }
}
{
  "error": {
    "root_cause": [
      {
        "type": "mapper_parsing_exception",
        "reason": "No handler for type [string] declared on field [name]"
      }
    ],
    "type": "mapper_parsing_exception",
    "reason": "Failed to parse mapping [type]: No handler for type [string] declared on field [name]",
    "caused_by": {
      "type": "mapper_parsing_exception",
      "reason": "No handler for type [string] declared on field [name]"
    }
  },
  "status": 400
}

Synonym Token Filter のtokenizerignore_caseが指定不可となります

Synonym Token Filter のトークナイザー指定が不可となります。tokenizerignore_caseは 5系で作成したインデックスでは機能しますが、6系で作成したインデックスでは機能しません。

インデックステンプレートの適用インデックス指定方法が変わります

Elasticsearch はインデックステンプレートによりインデックスの標準設定を定義することができます。インデックステンプレートを適用するインデックスのパターン指定フィールドがtemplateだったものが、index_patternsを使用するように変更されます。6.0.0-beta2 現在は引き続きtemplateフィールドも指定可能です。

スクリプティングの Groovy/JavaScript/Python 言語の廃止

Elasticsearch はフィールドやソートなど様々なところに動的に定義するスクリプティングがあります。Elasticsearch 5系から Groovy/JavaScript/Python は非推奨となり、Elasticsearch 標準の Painless の利用を推奨していました。Elasticsearch 6系から非推奨となった言語は廃止されました。

Java High Level REST Client

Java の SDK は古くから TransportClient を利用できました。5系から Web API へアクセスする Java REST Client がリリースされました。ただし、Java REST Client は TransportClient と比べると機能が少なく、アプリケーション側で多くを実装する必要がありました。5.6.0 からアプリケーションの実装を楽にしてくれる Java High Level REST Client がリリースされました。それに伴い、もともとあった TransportClient はこちらに置き換わっていくようです。

まとめ

いかがでしたでしょうか?

繰り返しとなりますが、今回本ブログエントリに記載したものは Breaking Changes のほんの一部となります。現状 Elasticsearch を利用されていて、6系の利用を考えている方はドキュメントを一通り確認した方がいいです。中には私が扱ったことがない機能にも触れられていて、影響を理解できないものもあったので他にもクリティカルな項目があったら是非教えてください。