最新のElasticsearch Rails(7系)のcreate_index!でclass_cast_exceptionが出る件(原因不明)
Elasticsearch-railsを試そうと思ったところ、インデックスを作成するところでエラーとなり詰まりました。
結論としては原因不明で解消していませんが、使用するElasticsearchのバージョンを下げて回避しました。
環境
- Ruby 2.6.3
- Rails 5.2.4
- elasticsearch-rails 7.0.0
- elasticsearch-model 7.0.0
- Elasticsearch 7.4.0 (Dockerイメージ)
下記の記事を参考にさせていただきElasticsearchを試す環境を構築しています。
この記事で使用しているElasticsearhのバージョンは6.7.2ですが、私は最新版の7.4.0を使用しました。以下のURLでDockerイメージのElasticsearchバージョンを確認できます。
7系だとエラーになる?
qiitaの記事を参考にしてsearchable.rb
というmoduleを用意し以下のようにcreate_index!
を定義します。このmoduleをarticle.rb
にincludeします。
class_methods do def create_index! client = __elasticsearch__.client client.indices.delete index: self.index_name rescue nil client.indices.create(index: self.index_name, body: { settings: self.settings.to_hash, mappings: self.mappings.to_hash }) end end
rails console
でインデックスを作成するために以下のコマンドを叩いてみたところエラーとなります。
Javaのキャストのエラーが出ていますが原因不明です。。。
irb(main):001:0> Article.create_index! Traceback (most recent call last): 2: from (irb):1 1: from app/models/concerns/searchable.rb:57:in `create_index!' Elasticsearch::Transport::Transport::Errors::InternalServerError ([500] {"error":{"root_cause":[{"type":"class_cast_exception","reason":"class java.lang.String cannot be cast to class java.util.Map (java.lang.String and java.util.Map are in module java.base of loader 'bootstrap')"}],"type":"class_cast_exception","reason":"class java.lang.String cannot be cast to class java.util.Map (java.lang.String and java.util.Map are in module java.base of loader 'bootstrap')"},"status":500})
独自定義したcreate_index!
ではなくelasticsearch-model自体で定義されている同メソッドを読んでも同じ結果でした。
irb(main):002:0> Article.__elasticsearch__.create_index! Traceback (most recent call last): 2: from (irb):2 1: from (irb):2:in `rescue in irb_binding' Elasticsearch::Transport::Transport::Errors::InternalServerError ([500] {"error":{"root_cause":[{"type":"class_cast_exception","reason":"class java.lang.String cannot be cast to class java.util.Map (java.lang.String and java.util.Map are in module java.base of loader 'bootstrap')"}],"type":"class_cast_exception","reason":"class java.lang.String cannot be cast to class java.util.Map (java.lang.String and java.util.Map are in module java.base of loader 'bootstrap')"},"status":500})
ちなみに、Elasticsearchのsettings
やmappings
はqiitaの記事とは異なりカスタマイズしていますがこれが原因ではないと思っています。
バージョンを下げてエラー回避
Elasticsearch7.4.0とelasticsearch-rails7系のgemを使うのをやめて、qiitaの記事と同バージョンのElasticsearch6.7.2と6.x系のgemを使えば上記エラーは出ませんでした。
# gem名だけだと最新版の7系になるので、6.x系の指定をする gem 'elasticsearch-rails', git: 'git://github.com/elastic/elasticsearch-rails.git', branch: '6.x' gem 'elasticsearch-model', git: 'git://github.com/elastic/elasticsearch-rails.git', branch: '6.x'
FROM docker.elastic.co/elasticsearch/elasticsearch:6.7.2
irb(main):001:0> Article.create_index! => {"acknowledged"=>true, "shards_acknowledged"=>true, "index"=>"es_articles_development"}
とりあえずバージョン下げればちゃんとインデックス作成できたので、いつか原因究明したいと思います。
エラーをみた感じだと、ElasticsearchのDockerイメージのJavaが問題なのかもしれません。。。