require 'elasticsearch/rails/tasks/import' namespace :elasticsearch do desc 'Rebuild index with zerodown time' task rebuild: :environment do size = (ENV['size'].presence || 1000).to_i model = ENV['model'].to_s.classify.constantize delete_old_index = ENV['delete'].present? es = model.__elasticsearch__ count = 0 total = model.count origin_index_name = model.index_name new_index_name = "#{origin_index_name}_#{Time.current.strftime('%Y%m%d%H%M%S')}" model.find_in_batches(batch_size: size) do |group| actions = group.map do |record| count += 1 puts "Import #{model} to #{new_index_name} #{count}/#{total}" { index: { _id: record.id, data: record.as_indexed_json } } end es.client.bulk( index: new_index_name, type: model.document_type, body: actions ) end old_indices = begin es.client.indices.get_alias(name: origin_index_name).keys rescue Elasticsearch::Transport::Transport::Errors::NotFound {} end actions = old_indices.map do |old_index_name| { remove: { index: old_index_name, alias: origin_index_name } } end actions << { add: { index: new_index_name, alias: origin_index_name } } es.client.indices.update_aliases(body: { actions: actions }) puts "Alias #{new_index_name} to #{origin_index_name}" next unless delete_old_index old_indices.each do |old_index_name| puts "Delete #{old_index_name}" es.client.indices.delete(index: old_index_name) end end end