Elasticsearch 6 → 7 に upgrade してみた


ES 6.3 → ES 7.10 にがんばってupgradeしたので、コードに変更が発生したところをメモってみる。

# 前提知識
- ES7は、deprecatedなものがまだ微妙にサポートされている
- ES8 になると、それがすべて非対応になる予定
- できるだけ ES8 でも使えるように直した

# Reference
最も変更が記載されてるのは v7.0 の breaking-changes です。一読して自分が使ってる機能がないか確認必須。私はJOINがあって焦りました。
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/breaking-changes-7.0.html
https://www.elastic.co/guide/en/cloud/current/ec-upgrading-v7.html

# 変更点


## Typeの廃止

これが一番大きい影響。mysqlでいう table が type. 一般的には _doc が使われています。_doc が廃止されてます（が、ほとんどのAPIではまだ使える）。

ES6では `_doc` しか使ってなかったので大きな影響はなかった。もし任意のtype使ってる場合は、reindexでmergeしろって書いてた。やってなくてよかった。

### Mapping API [変更必須] 
`_doc` が使えなくなったのは、mapping API. これは変更必須です。変えないと以下のエラーが出ます。

> The mapping definition cannot be nested under a type [_doc] unless include_type_name is set to true

```rb
# ES6
PUT myindex
{
	"settings": {
	    "number_of_shards": 5,
	    "number_of_replicas": 2
	},
	"mappings": {
	    "_doc": {                 <------------------- これを消す必要がある
	        "properties": {
	            "blahblah": {
 
# ES7
PUT myindex
{
	"settings": {
	    "number_of_shards": 5,
	    "number_of_replicas": 2
	},
	"mappings": {
        "properties": {
            "blahblah": {
```

typeを任意の文字で使ってしまっていた人は、ここが参考になるかも。↑のmappingハマリポイントも書いてありました。
https://www.elastic.co/blog/moving-from-types-to-typeless-apis-in-elasticsearch-7-0

### その他API

まだ _doc 付きでも使えますが、できれば ES8 対応に置き換えましょう.

```ruby
# ES6
PUT myindex/_doc/%s
# ES7
PUT myindex/_create/%s
 
# ES6
POST myindex/_doc/%s/_update
# ES7
PUT myindex/_update/%s
 
# ES6
DELETE myindex/%s
# ES7
# no update
```


## Hits.total が取れなくなった

検索クエリでヒットした数が取れなくなりました。なんと hits.total が int から dict になってました。鬼変更。

```rb
GET myindex/_search?q=blah:blah

# ES6
{
    "took": 1573,
    "timed_out": false,
    "_shards":
    {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits":
    {
        "total": 4396,       <---------- int 
        "max_score": null,
        "hits":
        [
            {
                "_index": "myindex",
                "_type": "_doc",
                "_id": "myid",
                "_score": null,
                "_source":
                {
                	...
                },
 
# ES7
GET myindex/_search?q=blah:blah
{
    "took": 1573,
    "timed_out": false,
    "_shards":
    {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits":
    {
        "total":        <------- dict になってる !!!!!!!
        {
            "value": 4396,     <------- hits.total.value で取りましょう
            "relation": "eq"
        },
        "max_score": null,
        "hits":
        [
            {
                "_index": "myindex",
                "_type": "_doc",        <--- 将来的になくなるので、型管理してる場合は Optional にしておきましょう
                "_id": "myid",
                "_score": null,
                "_source":
                {
                	...
                },
```


## JOIN
使ってる人は少ないと思うけど、私はがっつり使ってました
任意のpk(mysql joinでいうところの ON x.id = z.id  の "id") を指定できるが、何も指定しないと _id が使われる様子。なので、元の書き方のままで移行できました。

前の使い方はここに書いてある
https://qiita.com/uturned0/items/24fff526391d9eae6452

```rb
# ES7
PUT my-index-000001
{
  "mappings": {
    "properties": {
      "my_id": {               <---------- ここが増えた。が、なくても動く（_idが使われる)
        "type": "keyword"     <----------
      },                  <----------
      "my_join_field": { 
        "type": "join",
        "relations": {
          "question": "answer" 
        }
      }
    }
  }
}
```
> https://www.elastic.co/guide/en/elasticsearch/reference/6.3/parent-join.html
https://www.elastic.co/guide/en/elasticsearch/reference/7.16/parent-join.html



がんばって移行しましょう！！