class Chewy::Index::Import::BulkBuilder
This class purpose is to build ES client-acceptable bulk request body from the passed objects for index and deletion. It handles parent-child relationships as well by fetching existing documents from ES, taking their `_parent` field and using it in the bulk body. If fields are passed - it creates partial update entries except for the cases when the type has parent and parent_id has been changed.
Public Class Methods
@param index [Chewy::Index] desired index @param to_index [Array<Object>] objects to index @param delete [Array<Object>] objects or ids to delete @param fields [Array<Symbol, String>] and array of fields for documents update
# File lib/chewy/index/import/bulk_builder.rb, line 16 def initialize(index, to_index: [], delete: [], fields: []) @index = index @to_index = to_index @delete = delete @fields = fields.map!(&:to_sym) end
Public Instance Methods
Returns ES API-ready bulk requiest body. @see github.com/elastic/elasticsearch-ruby/blob/master/elasticsearch-api/lib/elasticsearch/api/actions/bulk.rb @return [Array<Hash>] bulk body
# File lib/chewy/index/import/bulk_builder.rb, line 26 def bulk_body @bulk_body ||= @to_index.flat_map(&method(:index_entry)).concat( @delete.flat_map(&method(:delete_entry)) ) end
The only purpose of this method is to cache document ids for all the passed object for index to avoid ids recalculation.
@return [Hash[String => Object]] an ids-objects index hash
# File lib/chewy/index/import/bulk_builder.rb, line 36 def index_objects_by_id @index_objects_by_id ||= index_object_ids.invert.stringify_keys! end
Private Instance Methods
# File lib/chewy/index/import/bulk_builder.rb, line 42 def crutches @crutches ||= Chewy::Index::Crutch::Crutches.new @index, @to_index end
# File lib/chewy/index/import/bulk_builder.rb, line 83 def delete_entry(object) entry = {} entry[:_id] = entry_id(object) entry[:_id] ||= object.as_json return [] if entry[:_id].blank? if parents parent = entry[:_id].present? && parents[entry[:_id].to_s] return [] unless parent entry[:parent] = parent end [{delete: entry}] end
# File lib/chewy/index/import/bulk_builder.rb, line 100 def entry_id(object) if type_root.id type_root.compose_id(object) else id = object.id if object.respond_to?(:id) id ||= object[:id] || object['id'] if object.is_a?(Hash) id = id.to_s if defined?(BSON) && id.is_a?(BSON::ObjectId) id end end
# File lib/chewy/index/import/bulk_builder.rb, line 60 def index_entry(object) entry = {} entry[:_id] = index_object_ids[object] if index_object_ids[object] if parents entry[:parent] = type_root.compose_parent(object) parent = entry[:_id].present? && parents[entry[:_id].to_s] end if parent && entry[:parent].to_s != parent entry[:data] = @index.compose(object, crutches) [{delete: entry.except(:data).merge(parent: parent)}, {index: entry}] elsif @fields.present? return [] unless entry[:_id] entry[:data] = {doc: @index.compose(object, crutches, fields: @fields)} [{update: entry}] else entry[:data] = @index.compose(object, crutches) [{index: entry}] end end
# File lib/chewy/index/import/bulk_builder.rb, line 111 def index_object_ids @index_object_ids ||= @to_index.each_with_object({}) do |object, result| id = entry_id(object) result[object] = id if id.present? end end
# File lib/chewy/index/import/bulk_builder.rb, line 46 def parents return unless type_root.parent_id @parents ||= begin ids = @index.map do |object| object.respond_to?(:id) ? object.id : object end ids.concat(@delete.map do |object| object.respond_to?(:id) ? object.id : object end) @index.filter(ids: {values: ids}).order('_doc').pluck(:_id, :_parent).to_h end end
# File lib/chewy/index/import/bulk_builder.rb, line 118 def type_root @type_root ||= @index.root end