Ruby on Rails项目中Elasticsearch 5.1.2与Tire索引导入报错求助
最近我在开发一个基于Ruby 2.4.0和Rails 5的项目,想用Elasticsearch实现应用内搜索功能,我的VenueDetail模型代码是这样的:
class VenueDetail < ActiveRecord::Base include Tire::Model::Search include Tire::Model::Callbacks settings index: { number_of_shards: 1, number_of_replicas: 0, } do mapping do indexes :id, :index => :not_analyzed indexes :venue_name, :type => 'string', :index => :analyzed end end def self.search(params) if params[:query].present? tire.search(load: true) do query { string "*#{params[:query]}*", default_operator: "AND" } size 100 end else tire.search(load: true) do query { string "*#{params[:term]}*", default_operator: "AND"} size 100 end end end end
但当我用Elasticsearch 5.1.2版本执行索引导入命令:
rake environment tire:import CLASS=VenueDetail FORCE=true
时,直接报错了:
There has been an error when creating the index -- elasticsearch returned: 400 : No handler found for uri [/venue_details] and method [POST]
折腾了一番后,终于找到了解决办法,分享给大家:
问题根源
Tire这个gem已经多年没有维护了,它的API是针对Elasticsearch 2.x及更早版本设计的。而Elasticsearch 5.x彻底重构了索引创建的API规则,Tire用的旧POST请求方式在ES5.x里已经不被支持,这就是报错的核心原因。
两种解决方案
1. 替换为官方维护的Elasticsearch-Rails gem(推荐长期使用)
这是最靠谱的方案,因为Elasticsearch官方维护的elasticsearch-rails和elasticsearch-model完全适配ES5.x及更高版本,后续更新也有保障。具体步骤:
更新Gemfile:删掉
tire,添加这两个gem:gem 'elasticsearch-rails' gem 'elasticsearch-model'然后跑
bundle install更新依赖。重构VenueDetail模型:
class VenueDetail < ActiveRecord::Base include Elasticsearch::Model include Elasticsearch::Model::Callbacks settings index: { number_of_shards: 1, number_of_replicas: 0 } do mappings dynamic: false do indexes :id, type: 'integer', index: false indexes :venue_name, type: 'text', analyzer: 'standard' end end def self.search(params) # 优先取query参数,没有的话用term,都没有就查全部 query_term = params[:query].presence || params[:term].presence || '*' __elasticsearch__.search( query: { wildcard: { venue_name: "*#{query_term}*" } }, size: 100 ).records end end创建索引并导入数据:
先清理掉旧的Tire索引(如果有的话),然后执行这两条命令:rails runner "VenueDetail.__elasticsearch__.create_index!" rails runner "VenueDetail.import"
2. 临时降级Elasticsearch到2.x版本(权宜之计)
如果暂时没时间重构代码,可以把Elasticsearch降级到2.4.6版本,这个版本和Tire的兼容性还不错。但要注意,ES2.x已经停止维护了,存在安全漏洞,不建议长期用这个方案。
内容的提问来源于stack exchange,提问作者awsm sid

