From 84edaf56c0c9e3a980bf76e2f20550c0053142b3 Mon Sep 17 00:00:00 2001 From: Amol Patil Date: Thu, 14 Nov 2024 16:35:29 +0530 Subject: [PATCH 1/8] Amol/v7.6.0 fork (#15) * added changes for apollo fork * added searchable proc support * added mongoid support * commented mongoid methods * added new files * uncommented mongoid methods * commented again * added mongo id adapter import * removed redundant merge * added logic for determining if direct import is needed * added index types * Added handling for mongo direct import in mongoid adapter * Fix rubocop class length limit * Changed handling for indextype * fixed rubocop errors * fixed override for import objects in mongoid adapter * fixed arguments to import objects mongoid override * temp revert override * changed index type * reverted to old logic * Revert "temp revert override" This reverts commit 420d4cd2e021f69bed0fd29200d83c242b83f3bf. * fixed elastic clients * changed added for passing chewy handled errors from https://github.com/apolloio/chewy/pull/16 * revert count behavior --------- Co-authored-by: Akshay Goel --- .rubocop_todo.yml | 4 +- Gemfile | 1 + lib/chewy.rb | 29 ++++- lib/chewy/config.rb | 4 +- lib/chewy/elastic_client.rb | 8 +- lib/chewy/index.rb | 10 ++ lib/chewy/index/actions.rb | 20 +-- lib/chewy/index/adapter/mongoid.rb | 87 +++++++++++++ lib/chewy/index/adapter/orm.rb | 2 +- lib/chewy/index/aliases.rb | 6 +- lib/chewy/index/crutch.rb | 7 +- lib/chewy/index/import/bulk_request.rb | 2 +- lib/chewy/index/observe/mongoid_methods.rb | 20 +++ lib/chewy/index/syncer.rb | 2 +- lib/chewy/multi_search.rb | 2 +- lib/chewy/runtime.rb | 4 +- lib/chewy/search.rb | 2 +- lib/chewy/search/parameters.rb | 139 ++++++++++++++++++++- lib/chewy/search/request.rb | 44 +++++-- lib/chewy/search/scrolling.rb | 4 +- 20 files changed, 346 insertions(+), 51 deletions(-) create mode 100644 lib/chewy/index/adapter/mongoid.rb create mode 100644 lib/chewy/index/observe/mongoid_methods.rb diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index de4efe5b1..9e43e89af 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -49,7 +49,7 @@ Metrics/AbcSize: # Offense count: 4 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 267 + Max: 300 # Offense count: 13 # Configuration parameters: IgnoredMethods. @@ -69,7 +69,7 @@ Metrics/ModuleLength: # Offense count: 18 # Configuration parameters: IgnoredMethods. Metrics/PerceivedComplexity: - Max: 13 + Max: 14 # Offense count: 11 # Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers. diff --git a/Gemfile b/Gemfile index e838bbb9d..3240a6985 100644 --- a/Gemfile +++ b/Gemfile @@ -6,6 +6,7 @@ gem 'activejob', require: false gem 'sidekiq', require: false gem 'kaminari-core', require: false +gem 'mongoid' gem 'parallel', require: false gem 'ruby-progressbar', require: false diff --git a/lib/chewy.rb b/lib/chewy.rb index 919f9bac8..05deb06d0 100644 --- a/lib/chewy.rb +++ b/lib/chewy.rb @@ -36,6 +36,10 @@ def try_require(path) try_require 'kaminari/activerecord' end +ActiveSupport.on_load(:mongoid) do + try_require 'kaminari/mongoid' +end + require 'chewy/version' require 'chewy/errors' require 'chewy/config' @@ -55,8 +59,19 @@ def try_require(path) include Chewy::Index::Observe::ActiveRecordMethods end +# ActiveSupport.on_load(:mongoid) do +# module Mongoid +# module Document +# module ClassMethods +# include Chewy::Index::Observe::MongoidMethods +# end +# end +# end +# end + module Chewy @adapters = [ + Chewy::Index::Adapter::Mongoid, Chewy::Index::Adapter::ActiveRecord, Chewy::Index::Adapter::Object ] @@ -97,8 +112,14 @@ def derive_name(index_name) # Main elasticsearch-ruby client instance # - def client - Chewy.current[:chewy_client] ||= Chewy::ElasticClient.new + def client(hosts = nil) + # # We are changing this to support multiple clusters in chewy. + thread_cache_key = if hosts + "chewy_client_#{hosts}" + else + 'chewy_client' + end + Chewy.current[thread_cache_key.to_sym] ||= Chewy::ElasticClient.new(hosts) end # Sends wait_for_status request to ElasticSearch with status @@ -108,7 +129,7 @@ def client # def wait_for_status if Chewy.configuration[:wait_for_status].present? - client.cluster.health wait_for_status: Chewy.configuration[:wait_for_status] + client(@hosts_name).cluster.health wait_for_status: Chewy.configuration[:wait_for_status] end end @@ -116,7 +137,7 @@ def wait_for_status # Be careful, if current prefix is blank, this will destroy all the indexes. # def massacre - Chewy.client.indices.delete(index: [Chewy.configuration[:prefix], '*'].reject(&:blank?).join('_')) + Chewy.client(@hosts_name).indices.delete(index: [Chewy.configuration[:prefix], '*'].reject(&:blank?).join('_')) Chewy.wait_for_status end alias_method :delete_all, :massacre diff --git a/lib/chewy/config.rb b/lib/chewy/config.rb index 1ec687e1b..dedcb46ae 100644 --- a/lib/chewy/config.rb +++ b/lib/chewy/config.rb @@ -70,12 +70,12 @@ def initialize end def transport_logger=(logger) - Chewy.client.transport.transport.logger = logger + Chewy.client(@hosts_name).transport.transport.logger = logger @transport_logger = logger end def transport_tracer=(tracer) - Chewy.client.transport.transport.tracer = tracer + Chewy.client(@hosts_name).transport.transport.tracer = tracer @transport_tracer = tracer end diff --git a/lib/chewy/elastic_client.rb b/lib/chewy/elastic_client.rb index 41a985ccc..be2d7d7ef 100644 --- a/lib/chewy/elastic_client.rb +++ b/lib/chewy/elastic_client.rb @@ -1,15 +1,17 @@ module Chewy # Replacement for Chewy.client class ElasticClient - def self.build_es_client(configuration = Chewy.configuration) + def self.build_es_client(hosts = nil, configuration = Chewy.configuration) client_configuration = configuration.deep_dup + client_configuration[:hosts] = client_configuration[hosts] if hosts client_configuration.delete(:prefix) # used by Chewy, not relevant to Elasticsearch::Client block = client_configuration[:transport_options].try(:delete, :proc) ::Elasticsearch::Client.new(client_configuration, &block) end - def initialize(elastic_client = self.class.build_es_client) - @elastic_client = elastic_client + def initialize(hosts = nil) + @elastic_client ||= self.class.build_es_client(hosts) + @elastic_client end private diff --git a/lib/chewy/index.rb b/lib/chewy/index.rb index 4c63cd8e4..3675d7ea9 100644 --- a/lib/chewy/index.rb +++ b/lib/chewy/index.rb @@ -1,6 +1,7 @@ require 'chewy/search' require 'chewy/index/actions' require 'chewy/index/adapter/active_record' +require 'chewy/index/adapter/mongoid' require 'chewy/index/adapter/object' require 'chewy/index/aliases' require 'chewy/index/crutch' @@ -48,6 +49,8 @@ class Index self._default_import_options = {} class << self + attr_reader :hosts_name + # @overload index_name(suggest) # If suggested name is passed, it is set up as the new base name for # the index. Used for the index base name redefinition. @@ -92,6 +95,13 @@ def index_name(suggest = nil, prefix: nil, suffix: nil) end end + # Sets the hosts name of the index. If hosts_name is nil, use the default + # hosts in chewy.yml. Otherwise use the hosts with the specified name for + # indexing/queries. + def es_cluster_host(hosts_name) + @hosts_name = hosts_name + end + # Base name for the index. Uses the default value inferred from the # class name unless redefined. # diff --git a/lib/chewy/index/actions.rb b/lib/chewy/index/actions.rb index afc7debcc..3bd92354d 100644 --- a/lib/chewy/index/actions.rb +++ b/lib/chewy/index/actions.rb @@ -12,7 +12,7 @@ module ClassMethods # UsersIndex.exists? #=> true # def exists? - client.indices.exists(index: index_name) + client(@hosts_name).indices.exists(index: index_name) end # Creates index and applies mappings and settings. @@ -59,7 +59,7 @@ def create!(suffix = nil, **options) body = specification_hash body[:aliases] = {general_name => {}} if options[:alias] && suffixed_name != general_name - result = client.indices.create(index: suffixed_name, body: body) + result = client(@hosts_name).indices.create(index: suffixed_name, body: body) Chewy.wait_for_status if result result @@ -79,8 +79,8 @@ def delete(suffix = nil) # "The index parameter in the delete index API no longer accepts alias names. # Instead, it accepts only index names (or wildcards which will expand to matching indices)." # https://www.elastic.co/guide/en/elasticsearch/reference/6.8/breaking-changes-6.0.html#_delete_index_api_resolves_indices_expressions_only_against_indices - index_names = client.indices.get_alias(index: index_name(suffix: suffix)).keys - result = client.indices.delete index: index_names.join(',') + index_names = client(@hosts_name).indices.get_alias(index: index_name(suffix: suffix)).keys + result = client(@hosts_name).indices.delete index: index_names.join(',') Chewy.wait_for_status if result result # es-ruby >= 1.0.10 handles Elasticsearch::Transport::Transport::Errors::NotFound @@ -164,13 +164,13 @@ def reset!(suffix = nil, apply_journal: true, journal: false, **import_options) original_index_settings suffixed_name delete if indexes.blank? - client.indices.update_aliases body: {actions: [ + client(@hosts_name).indices.update_aliases body: {actions: [ *indexes.map do |index| {remove: {index: index, alias: general_name}} end, {add: {index: suffixed_name, alias: general_name}} ]} - client.indices.delete index: indexes if indexes.present? + client(@hosts_name).indices.delete index: indexes if indexes.present? self.journal.apply(start_time, **import_options) if apply_journal result @@ -192,11 +192,11 @@ def journal end def clear_cache(args = {index: index_name}) - client.indices.clear_cache(args) + client(@hosts_name).indices.clear_cache(args) end def reindex(source: index_name, dest: index_name) - client.reindex( + client(@hosts_name).reindex( { body: { @@ -214,7 +214,7 @@ def reindex(source: index_name, dest: index_name) # Chewy.client.update_mapping('cities', {properties: {new_field: {type: :text}}}) # def update_mapping(name = index_name, body = root.mappings_hash) - client.indices.put_mapping( + client(@hosts_name).indices.put_mapping( index: name, body: body )['acknowledged'] @@ -255,7 +255,7 @@ def original_index_settings(index_name) end def update_settings(index_name, **options) - client.indices.put_settings index: index_name, body: {index: options[:settings]} + client(@hosts_name).indices.put_settings index: index_name, body: {index: options[:settings]} end def index_settings(setting_name) diff --git a/lib/chewy/index/adapter/mongoid.rb b/lib/chewy/index/adapter/mongoid.rb new file mode 100644 index 000000000..ad4ed6a27 --- /dev/null +++ b/lib/chewy/index/adapter/mongoid.rb @@ -0,0 +1,87 @@ +require 'chewy/index/adapter/orm' + +module Chewy + class Index + module Adapter + class Mongoid < Orm + def self.accepts?(target) + defined?(::Mongoid::Document) && ( + (target.is_a?(Class) && target.ancestors.include?(::Mongoid::Document)) || + target.is_a?(::Mongoid::Criteria)) + end + + def identify(collection) + super(collection).map { |id| id.is_a?(BSON::ObjectId) ? id.to_s : id } + end + + private + + def cleanup_default_scope! + Chewy.logger.warn('Default type scope order, limit and offset are ignored and will be nullified') if Chewy.logger && sort_or_limit_or_skip_options? + + @default_scope.options.delete(:limit) + @default_scope.options.delete(:skip) + @default_scope = @default_scope.reorder(nil) + end + + def sort_or_limit_or_skip_options? + @default_scope.options.values_at(:sort, :limit, :skip).compact.present? + end + + def import_scope(scope, options) + pluck_in_batches(scope, **options.slice(:batch_size)).map do |ids| + yield grouped_objects(default_scope_where_ids_in(ids)) + end.all? + end + + def import_objects(collection, options) + direct_import = (default_scope.selector.empty? || @options[:searchable_proc]) && + !options[:raw_import] && + collection.is_a?(Array) && + !collection.empty? && + collection.all? { |item| item.is_a?(::Mongoid::Document) && item.__selected_fields.nil? } + options[:direct_import] = direct_import unless options[:direct_import].present? + super(collection, options) + end + + def primary_key + :_id + end + + def pluck(scope, fields: []) + scope.pluck(primary_key, *fields) + end + + def pluck_in_batches(scope, fields: [], batch_size: nil, **options, &block) + unless block_given? + return enum_for( + :pluck_in_batches, + scope, + fields: fields, + batch_size: batch_size, + **options + ) + end + + scope.batch_size(batch_size).no_timeout.pluck(primary_key, *fields).each_slice(batch_size, &block) + end + + def scope_where_ids_in(scope, ids) + scope.where(primary_key.in => ids) + end + + def all_scope + target.all + end + + def relation_class + ::Mongoid::Criteria + end + + def object_class + ::Mongoid::Document + end + end + end + end +end diff --git a/lib/chewy/index/adapter/orm.rb b/lib/chewy/index/adapter/orm.rb index c86b6d06b..ed2e8c281 100644 --- a/lib/chewy/index/adapter/orm.rb +++ b/lib/chewy/index/adapter/orm.rb @@ -124,7 +124,7 @@ def import_objects(collection, options) else default_scope_where_ids_in(ids) end - + batch = batch.select { |object| @options[:searchable_proc].call(object) } if @options[:searchable_proc].present? if batch.empty? true else diff --git a/lib/chewy/index/aliases.rb b/lib/chewy/index/aliases.rb index cfcf74732..c6cc6f7aa 100644 --- a/lib/chewy/index/aliases.rb +++ b/lib/chewy/index/aliases.rb @@ -5,14 +5,14 @@ module Aliases module ClassMethods def indexes - indexes = empty_if_not_found { client.indices.get(index: index_name).keys } - indexes += empty_if_not_found { client.indices.get_alias(name: index_name).keys } + indexes = empty_if_not_found { client(@hosts_name).indices.get(index: index_name).keys } + indexes += empty_if_not_found { client(@hosts_name).indices.get_alias(name: index_name).keys } indexes.compact.uniq end def aliases empty_if_not_found do - client.indices.get_alias(index: index_name, name: '*').values.flat_map do |aliases| + client(@hosts_name).indices.get_alias(index: index_name, name: '*').values.flat_map do |aliases| aliases['aliases'].keys end end.compact.uniq diff --git a/lib/chewy/index/crutch.rb b/lib/chewy/index/crutch.rb index 4377187af..2ccbcc6ec 100644 --- a/lib/chewy/index/crutch.rb +++ b/lib/chewy/index/crutch.rb @@ -26,7 +26,12 @@ def respond_to_missing?(name, include_private = false) end def [](name) - @crutches_instances[name] ||= @index._crutches[:"#{name}"].call(@collection) + execution_block = @index._crutches[:"#{name}"] + @crutches_instances[name] ||= if execution_block.arity == 2 + execution_block.call(@collection, self) + else + execution_block.call(@collection) + end end end diff --git a/lib/chewy/index/import/bulk_request.rb b/lib/chewy/index/import/bulk_request.rb index 67f8ceb5d..160d4e04d 100644 --- a/lib/chewy/index/import/bulk_request.rb +++ b/lib/chewy/index/import/bulk_request.rb @@ -33,7 +33,7 @@ def perform(body) return [] if body.blank? request_bodies(body).each_with_object([]) do |request_body, results| - response = @index.client.bulk(**request_base.merge(body: request_body)) if request_body.present? + response = @index.client(@index.hosts_name).bulk(**request_base.merge(body: request_body)) if request_body.present? next unless response.try(:[], 'errors') diff --git a/lib/chewy/index/observe/mongoid_methods.rb b/lib/chewy/index/observe/mongoid_methods.rb new file mode 100644 index 000000000..661000fe3 --- /dev/null +++ b/lib/chewy/index/observe/mongoid_methods.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Chewy + class Index + module Observe + extend Helpers + module MongoidMethods + class_methods do + def update_index(type_name, *args, &block) + # callback_options = Observe.extract_callback_options!(args) + # update_proc = Observe.update_proc(type_name, *args, &block) + # + # after_save(callback_options, &update_proc) + # after_destroy(callback_options, &update_proc) + end + end + end + end + end +end diff --git a/lib/chewy/index/syncer.rb b/lib/chewy/index/syncer.rb index b8365bb50..ffcea38b9 100644 --- a/lib/chewy/index/syncer.rb +++ b/lib/chewy/index/syncer.rb @@ -208,7 +208,7 @@ def outdated_sync_field_type return @outdated_sync_field_type if instance_variable_defined?(:@outdated_sync_field_type) return unless @index.outdated_sync_field - mappings = @index.client.indices.get_mapping(index: @index.index_name).values.first.fetch('mappings', {}) + mappings = @index.client(@index.hosts_name).indices.get_mapping(index: @index.index_name).values.first.fetch('mappings', {}) @outdated_sync_field_type = mappings .fetch('properties', {}) diff --git a/lib/chewy/multi_search.rb b/lib/chewy/multi_search.rb index b33ede63d..911ff57c5 100644 --- a/lib/chewy/multi_search.rb +++ b/lib/chewy/multi_search.rb @@ -52,7 +52,7 @@ def msearch(queries_to_search) [rendered.except(:body), rendered[:body]] end - client.msearch(body: body) + client(@hosts_name).msearch(body: body) end end diff --git a/lib/chewy/runtime.rb b/lib/chewy/runtime.rb index aa404979c..018b272d0 100644 --- a/lib/chewy/runtime.rb +++ b/lib/chewy/runtime.rb @@ -2,8 +2,8 @@ module Chewy module Runtime - def self.version - Chewy.current[:chewy_runtime_version] ||= Version.new(Chewy.client.info['version']['number']) + def self.version(hosts = nil) + Chewy.current[:chewy_runtime_version] ||= Version.new(Chewy.client(hosts).info['version']['number']) end end end diff --git a/lib/chewy/search.rb b/lib/chewy/search.rb index be2ba29a3..36f9b6da5 100644 --- a/lib/chewy/search.rb +++ b/lib/chewy/search.rb @@ -49,7 +49,7 @@ def all # @return [Hash] the request result def search_string(query, options = {}) options = options.merge(all.render.slice(:index).merge(q: query)) - Chewy.client.search(options) + Chewy.client(@hosts_name).search(options) end # Delegates methods from the request class to the index class diff --git a/lib/chewy/search/parameters.rb b/lib/chewy/search/parameters.rb index 3f55e0384..a084236f8 100644 --- a/lib/chewy/search/parameters.rb +++ b/lib/chewy/search/parameters.rb @@ -97,15 +97,21 @@ def except!(names) # @return [{Symbol => Chewy::Search::Parameters::Storage}] storages from other parameters def merge!(other) other.storages.each do |name, storage| - modify!(name) { merge!(storage) } + # Handle query-related storages with a specialized merge function + if name.to_sym.in? %i[query filter post_filter] + merge_queries_and_filters(name, storage) + else + # For other types of storages, use a general purpose merge method + modify!(name) { merge!(storage) } + end end end # Renders and merges all the parameter storages into a single hash. # # @return [Hash] request body - def render - render_query_string_params.merge(render_body) + def render(replace_post_filter: false) + render_query_string_params.merge(render_body(replace_post_filter: replace_post_filter)) end protected @@ -137,16 +143,17 @@ def render_query_string_params end end - def render_body + def render_body(replace_post_filter: false) exceptions = %i[filter query none] + QUERY_STRING_STORAGES + exceptions += %i[post_filter] if replace_post_filter body = @storages.except(*exceptions).values.inject({}) do |result, storage| result.merge!(storage.render || {}) end - body.merge!(render_query || {}) + body.merge!(render_query(replace_post_filter: replace_post_filter) || {}) {body: body} end - def render_query + def render_query(replace_post_filter: false) none = @storages[:none].render return none if none @@ -154,6 +161,16 @@ def render_query filter = @storages[:filter].render query = @storages[:query].render + if replace_post_filter + post_filter = @storages[:post_filter].render + if post_filter + query = if query + {query: {bool: {must: [query[:query], post_filter[:post_filter]]}}} + else + {query: {bool: {must: [post_filter[:post_filter]]}}} + end + end + end return query unless filter if query && query[:query][:bool] @@ -165,6 +182,116 @@ def render_query {query: {bool: filter}} end end + + private + + # Smartly wraps a query in a bool must unless it is already correctly structured. + # This method helps maintain logical grouping and avoid unnecessary nesting in queries. + # + # @param [Hash, Array, Nil] query The query to wrap. + # @return [Hash, Array, Nil] The wrapped or original query. + # + # Example: + # input: { term: { status: 'active' } } + # output: { bool: { must: [{ term: { status: 'active' } }] } } + # + # input: { bool: { must: [{ term: { status: 'active' } }] } } + # output: { bool: { must: [{ term: { status: 'active' } }] } } + def smart_wrap_in_bool_must(query = nil) + return nil if query.nil? + + query = query.deep_symbolize_keys if query.is_a?(Hash) + + # Normalize to ensure it's always in an array form for 'must' unless already properly formatted. + normalized_query = query.is_a?(Array) ? query : [query] + + # Check if the query already has a 'bool' structure + if query.is_a?(Hash) && query.key?(:bool) + # Check the components of the 'bool' structure + has_only_must = query[:bool].key?(:must) && query[:bool].keys.size == 1 + + # If it has only a 'must' and nothing else, use it as is + if has_only_must + query + else + # If it contains other components like 'should' or 'must_not', wrap in a new 'bool' 'must' + {bool: {must: normalized_query}} + end + else + # If no 'bool' structure is present, wrap the query in a 'bool' 'must' + {bool: {must: normalized_query}} + end + end + + # Combines two boolean queries into a single well-formed boolean query without redundant nesting. + # + # @param [Hash, Array] query1 The first query component. + # @param [Hash, Array] query2 The second query component. + # @return [Hash] A combined boolean query. + # + # Example: + # query1: { bool: { must: [{ term: { status: 'active' } }] } } + # query2: { bool: { must: [{ term: { age: 25 } }] } } + # result: { bool: { must: [{ term: { status: 'active' } }, { term: { age: 25 } }] } } + def merge_bool_queries(query1, query2) + # Extract the :must components, ensuring they are arrays. ideally this should be the case anyway + # but this is a safety check for cases like OrganizationChartFilter where the query is not properly formatted. + # Eg index.query( + # { + # bool: { + # must: { + # term: { + # has_org_chart_note: has_org_chart_note + # } + # }, + # } + # } + # ) + must1 = ensure_array(query1.dig(:bool, :must)) + must2 = ensure_array(query2.dig(:bool, :must)) + + # Combine the arrays; if both are empty, wrap the entire queries as fallback. + if must1.empty? && must2.empty? + {bool: {must: [query1, query2].compact}} # Use compact to remove any nils. + else + {bool: {must: must1 + must2}} + end + end + + # Merges queries or filters from two different storages into a single storage efficiently. + # + # @param [Symbol] name The type of storage (query, filter, post_filter). + # @param [Storage] other_storage The storage object from another instance. + def merge_queries_and_filters(name, other_storage) + current_storage = storages[name] + # other_storage = other.storages[name] + # Render each storage to get the DSL + current_query = smart_wrap_in_bool_must(current_storage.render&.[](name)) + other_query = smart_wrap_in_bool_must(other_storage.render&.[](name)) + + if current_query && other_query + # Custom merging logic for queries and filters + + # Combine rendered queries inside a single bool must + combined_storage = merge_bool_queries(current_query, other_query) + + storages[name].replace!(combined_storage) # Directly set the modified storage + else + # Default merge if one is nil + replacement_query = current_query || other_query + storages[name].replace!(replacement_query) if replacement_query + end + end + + # Helper to ensure the :must key is always an array + def ensure_array(value) + case value + when Hash, nil + [value].compact # Wrap hashes or non-nil values in an array, remove nils. + else + value + end + end end end end diff --git a/lib/chewy/search/request.rb b/lib/chewy/search/request.rb index f3b1031b4..3a02a720a 100644 --- a/lib/chewy/search/request.rb +++ b/lib/chewy/search/request.rb @@ -46,7 +46,7 @@ class Request delegate :hits, :wrappers, :objects, :records, :documents, :object_hash, :record_hash, :document_hash, - :total, :max_score, :took, :timed_out?, to: :response + :total, :max_score, :took, :timed_out?, :errors, to: :response delegate :each, :size, :to_a, :[], to: :wrappers alias_method :to_ary, :to_a alias_method :total_count, :total @@ -77,6 +77,24 @@ def parameters @parameters ||= Parameters.new end + def x_opaque_id(x_opaque_id) + @x_opaque_id = x_opaque_id + end + + # Response `errors` field. Returns `nil` if there is no error. + # @return [Hash, nil] + def errors + return nil if @body.blank? + not_found_error = @body['not_found_error'] + # there's another case when failures could be present in some shards, in that case es returns them + # in @body[_shards][failures] array + shard_failures = @body['_shards']['failures'] if @body['_shards'] + { + not_found_error: not_found_error, + shard_failures: shard_failures + }.compact.presence + end + # Compare two scopes or scope with a collection of wrappers. # If other is a collection it performs the request to fetch # data from ES. @@ -115,10 +133,10 @@ def response=(from_elasticsearch) end # ES request body - # + # @param replace_post_filter [true, false] whether to replace post_filter with filter # @return [Hash] request body - def render - @render ||= parameters.render + def render(replace_post_filter: false) + @render ||= parameters.render(replace_post_filter: replace_post_filter) end # Includes the class name and the result of rendering. @@ -566,8 +584,8 @@ def reorder(value, *values) # @param values [true, false, String, Symbol, Array] # @return [Chewy::Search::Request] %i[source stored_fields].each do |name| - define_method name do |value, *values| - modify(name) { update!(values.empty? ? value : [value, *values]) } + define_method(name) do |value, *values| + modify(name) { update!([*value, *values, '_index_type']) } end end @@ -852,7 +870,9 @@ def count if performed? total else - Chewy.client.count(only(WHERE_STORAGES).render)['count'] + count_params = only(WHERE_STORAGES).render(replace_post_filter: true) + count_params.merge!({opaque_id: @x_opaque_id}) if @x_opaque_id + Chewy.client(_indices.first.hosts_name).count(count_params)['count'] end rescue Elasticsearch::Transport::Transport::Errors::NotFound 0 @@ -991,7 +1011,7 @@ def delete_all(refresh: true, wait_for_completion: nil, requests_per_second: nil ) ActiveSupport::Notifications.instrument 'delete_query.chewy', notification_payload(request: request_body) do request_body[:body] = {query: {match_all: {}}} if request_body[:body].empty? - Chewy.client.delete_by_query(request_body) + Chewy.client(_indices.first.hosts_name).delete_by_query(request_body) end end @@ -1034,9 +1054,11 @@ def reset def perform(additional = {}) request_body = render.merge(additional) ActiveSupport::Notifications.instrument 'search_query.chewy', notification_payload(request: request_body) do - Chewy.client.search(request_body) - rescue Elasticsearch::Transport::Transport::Errors::NotFound - {} + request_body.merge!({opaque_id: @x_opaque_id}) if @x_opaque_id + Chewy.client(_indices.first.hosts_name).search(request_body) + rescue Elasticsearch::Transport::Transport::Errors::NotFound => error + # passing error as a separate param down to the response, hence won't affect any other logic + { "not_found_error" => error } end end diff --git a/lib/chewy/search/scrolling.rb b/lib/chewy/search/scrolling.rb index 6074b3252..f8150e95c 100644 --- a/lib/chewy/search/scrolling.rb +++ b/lib/chewy/search/scrolling.rb @@ -44,7 +44,7 @@ def scroll_batches(batch_size: Request::DEFAULT_BATCH_SIZE, scroll: Request::DEF result = perform_scroll(scroll: scroll, scroll_id: scroll_id) end ensure - Chewy.client.clear_scroll(body: {scroll_id: scroll_id}) if scroll_id + Chewy.client(@hosts_name).clear_scroll(body: {scroll_id: scroll_id}) if scroll_id end # @!method scroll_hits(batch_size: 1000, scroll: '1m') @@ -129,7 +129,7 @@ def scroll_objects(**options, &block) def perform_scroll(body) ActiveSupport::Notifications.instrument 'search_query.chewy', notification_payload(request: body) do - Chewy.client.scroll(body) + Chewy.client(@hosts_name).scroll(body) end end end From f046163cd1db3301e9e4774bcd3c20b9e8945d35 Mon Sep 17 00:00:00 2001 From: Amol Patil Date: Fri, 15 Nov 2024 17:53:23 +0530 Subject: [PATCH 2/8] removed deep_dup for import fixed host name for some cases --- lib/chewy.rb | 10 +++++----- lib/chewy/config.rb | 6 ++++-- lib/chewy/index/import.rb | 7 +++++-- lib/chewy/multi_search.rb | 6 +++--- lib/chewy/search/request.rb | 10 +++++++--- lib/chewy/search/scrolling.rb | 4 ++-- 6 files changed, 26 insertions(+), 17 deletions(-) diff --git a/lib/chewy.rb b/lib/chewy.rb index 05deb06d0..ebc62c764 100644 --- a/lib/chewy.rb +++ b/lib/chewy.rb @@ -127,18 +127,18 @@ def client(hosts = nil) # # Does nothing in case of config `wait_for_status` is undefined. # - def wait_for_status + def wait_for_status(client) if Chewy.configuration[:wait_for_status].present? - client(@hosts_name).cluster.health wait_for_status: Chewy.configuration[:wait_for_status] + client.cluster.health wait_for_status: Chewy.configuration[:wait_for_status] end end # Deletes all corresponding indexes with current prefix from ElasticSearch. # Be careful, if current prefix is blank, this will destroy all the indexes. # - def massacre - Chewy.client(@hosts_name).indices.delete(index: [Chewy.configuration[:prefix], '*'].reject(&:blank?).join('_')) - Chewy.wait_for_status + def massacre(client) + client.indices.delete(index: [Chewy.configuration[:prefix], '*'].reject(&:blank?).join('_')) + wait_for_status(client) end alias_method :delete_all, :massacre diff --git a/lib/chewy/config.rb b/lib/chewy/config.rb index dedcb46ae..c487685c1 100644 --- a/lib/chewy/config.rb +++ b/lib/chewy/config.rb @@ -70,12 +70,14 @@ def initialize end def transport_logger=(logger) - Chewy.client(@hosts_name).transport.transport.logger = logger + # TODO Add support for hostname + Chewy.client.transport.transport.logger = logger @transport_logger = logger end def transport_tracer=(tracer) - Chewy.client(@hosts_name).transport.transport.tracer = tracer + # TODO Add support for hostname + Chewy.client.transport.transport.tracer = tracer @transport_tracer = tracer end diff --git a/lib/chewy/index/import.rb b/lib/chewy/index/import.rb index 8de6a877a..ac92feb31 100644 --- a/lib/chewy/index/import.rb +++ b/lib/chewy/index/import.rb @@ -128,12 +128,15 @@ def compose(object, crutches = nil, fields: []) private def intercept_import_using_strategy(*args) - args_clone = args.deep_dup - options = args_clone.extract_options! + options = args.extract_options! strategy = options.delete(:strategy) return import_routine(*args) if strategy.blank? + # We should evaluate impact of deep_dup if we pass any specific strategy in the import call + # Right now this is always blank in our case, so the code will never reach here + args_clone = args.deep_dup + ids = args_clone.flatten return {} if ids.blank? return {argument: {"#{strategy} supports ids only!" => ids}} unless ids.all? do |id| diff --git a/lib/chewy/multi_search.rb b/lib/chewy/multi_search.rb index 911ff57c5..9186dedd8 100644 --- a/lib/chewy/multi_search.rb +++ b/lib/chewy/multi_search.rb @@ -52,11 +52,11 @@ def msearch(queries_to_search) [rendered.except(:body), rendered[:body]] end - client(@hosts_name).msearch(body: body) + @client.msearch(body: body) end end - def self.msearch(queries) - Chewy::MultiSearch.new(queries) + def self.msearch(queries, client) + Chewy::MultiSearch.new(queries, client:) end end diff --git a/lib/chewy/search/request.rb b/lib/chewy/search/request.rb index 3a02a720a..7e302ffee 100644 --- a/lib/chewy/search/request.rb +++ b/lib/chewy/search/request.rb @@ -872,7 +872,7 @@ def count else count_params = only(WHERE_STORAGES).render(replace_post_filter: true) count_params.merge!({opaque_id: @x_opaque_id}) if @x_opaque_id - Chewy.client(_indices.first.hosts_name).count(count_params)['count'] + es_client.count(count_params)['count'] end rescue Elasticsearch::Transport::Transport::Errors::NotFound 0 @@ -1011,7 +1011,7 @@ def delete_all(refresh: true, wait_for_completion: nil, requests_per_second: nil ) ActiveSupport::Notifications.instrument 'delete_query.chewy', notification_payload(request: request_body) do request_body[:body] = {query: {match_all: {}}} if request_body[:body].empty? - Chewy.client(_indices.first.hosts_name).delete_by_query(request_body) + es_client.delete_by_query(request_body) end end @@ -1055,7 +1055,7 @@ def perform(additional = {}) request_body = render.merge(additional) ActiveSupport::Notifications.instrument 'search_query.chewy', notification_payload(request: request_body) do request_body.merge!({opaque_id: @x_opaque_id}) if @x_opaque_id - Chewy.client(_indices.first.hosts_name).search(request_body) + es_client.search(request_body) rescue Elasticsearch::Transport::Transport::Errors::NotFound => error # passing error as a separate param down to the response, hence won't affect any other logic { "not_found_error" => error } @@ -1073,6 +1073,10 @@ def _indices parameters[:indices].indices end + def es_client + Chewy.client(_indices.first.hosts_name) + end + def raw_limit_value parameters[:limit].value end diff --git a/lib/chewy/search/scrolling.rb b/lib/chewy/search/scrolling.rb index f8150e95c..c6f3cec85 100644 --- a/lib/chewy/search/scrolling.rb +++ b/lib/chewy/search/scrolling.rb @@ -44,7 +44,7 @@ def scroll_batches(batch_size: Request::DEFAULT_BATCH_SIZE, scroll: Request::DEF result = perform_scroll(scroll: scroll, scroll_id: scroll_id) end ensure - Chewy.client(@hosts_name).clear_scroll(body: {scroll_id: scroll_id}) if scroll_id + es_client.clear_scroll(body: {scroll_id: scroll_id}) if scroll_id end # @!method scroll_hits(batch_size: 1000, scroll: '1m') @@ -129,7 +129,7 @@ def scroll_objects(**options, &block) def perform_scroll(body) ActiveSupport::Notifications.instrument 'search_query.chewy', notification_payload(request: body) do - Chewy.client(@hosts_name).scroll(body) + es_client.scroll(body) end end end From b2224382e34de547991511957917a64fd1b17c82 Mon Sep 17 00:00:00 2001 From: Amol Patil Date: Fri, 15 Nov 2024 21:12:12 +0530 Subject: [PATCH 3/8] fixed wait_for_status references for other cases --- lib/chewy/index/actions.rb | 12 +++++++----- lib/chewy/index/import.rb | 4 +++- lib/chewy/index/import/routine.rb | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/chewy/index/actions.rb b/lib/chewy/index/actions.rb index 3bd92354d..8fa4add89 100644 --- a/lib/chewy/index/actions.rb +++ b/lib/chewy/index/actions.rb @@ -59,9 +59,10 @@ def create!(suffix = nil, **options) body = specification_hash body[:aliases] = {general_name => {}} if options[:alias] && suffixed_name != general_name - result = client(@hosts_name).indices.create(index: suffixed_name, body: body) + es_client = client(@hosts_name) + result = es_client.indices.create(index: suffixed_name, body: body) - Chewy.wait_for_status if result + Chewy.wait_for_status(es_client) if result result end @@ -79,9 +80,10 @@ def delete(suffix = nil) # "The index parameter in the delete index API no longer accepts alias names. # Instead, it accepts only index names (or wildcards which will expand to matching indices)." # https://www.elastic.co/guide/en/elasticsearch/reference/6.8/breaking-changes-6.0.html#_delete_index_api_resolves_indices_expressions_only_against_indices - index_names = client(@hosts_name).indices.get_alias(index: index_name(suffix: suffix)).keys - result = client(@hosts_name).indices.delete index: index_names.join(',') - Chewy.wait_for_status if result + es_client = client(@hosts_name) + index_names = es_client.indices.get_alias(index: index_name(suffix: suffix)).keys + result = es_client.indices.delete index: index_names.join(',') + Chewy.wait_for_status(es_client) if result result # es-ruby >= 1.0.10 handles Elasticsearch::Transport::Transport::Errors::NotFound # by itself, rescue is for previous versions diff --git a/lib/chewy/index/import.rb b/lib/chewy/index/import.rb index ac92feb31..ed9539946 100644 --- a/lib/chewy/index/import.rb +++ b/lib/chewy/index/import.rb @@ -103,7 +103,7 @@ def import!(*args) # @return [Hash] tricky transposed errors hash, empty if everything is fine def bulk(**options) error_items = BulkRequest.new(self, **options).perform(options[:body]) - Chewy.wait_for_status + Chewy.wait_for_status(es_client) payload_errors(error_items) end @@ -135,6 +135,8 @@ def intercept_import_using_strategy(*args) # We should evaluate impact of deep_dup if we pass any specific strategy in the import call # Right now this is always blank in our case, so the code will never reach here + # Check for our mongo data with invalid attributes, and setters which raise an exception if we want to + # call deep_dup args_clone = args.deep_dup ids = args_clone.flatten diff --git a/lib/chewy/index/import/routine.rb b/lib/chewy/index/import/routine.rb index 61004955a..edf8f7ae7 100644 --- a/lib/chewy/index/import/routine.rb +++ b/lib/chewy/index/import/routine.rb @@ -102,7 +102,7 @@ def process(index: [], delete: []) def perform_bulk(body) response = bulk.perform(body) yield response if block_given? - Chewy.wait_for_status + Chewy.wait_for_status(es_client) @errors.concat(response) response.blank? end From 2987c8f99f17a92e4f3e8ef425bbdecba9bdd110 Mon Sep 17 00:00:00 2001 From: Amol Patil Date: Fri, 15 Nov 2024 21:22:49 +0530 Subject: [PATCH 4/8] fixed routine --- lib/chewy/index/import.rb | 2 +- lib/chewy/index/import/routine.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/chewy/index/import.rb b/lib/chewy/index/import.rb index ed9539946..fac7c52cb 100644 --- a/lib/chewy/index/import.rb +++ b/lib/chewy/index/import.rb @@ -103,7 +103,7 @@ def import!(*args) # @return [Hash] tricky transposed errors hash, empty if everything is fine def bulk(**options) error_items = BulkRequest.new(self, **options).perform(options[:body]) - Chewy.wait_for_status(es_client) + Chewy.wait_for_status(client(@hosts_name)) payload_errors(error_items) end diff --git a/lib/chewy/index/import/routine.rb b/lib/chewy/index/import/routine.rb index edf8f7ae7..7614a06c7 100644 --- a/lib/chewy/index/import/routine.rb +++ b/lib/chewy/index/import/routine.rb @@ -61,6 +61,10 @@ def initialize(index, **options) @leftovers = [] end + def es_client + @index.client(@index.hosts_name) + end + # Creates the journal index and the corresponding index if necessary. # @return [Object] whatever def create_indexes! From 13948cfd88d54e025c194b18c304f2f277466349 Mon Sep 17 00:00:00 2001 From: Amol Patil Date: Fri, 15 Nov 2024 21:50:37 +0530 Subject: [PATCH 5/8] refactored es client --- lib/chewy/index.rb | 5 +++++ lib/chewy/index/actions.rb | 13 ++++++------- lib/chewy/index/aliases.rb | 6 +++--- lib/chewy/index/import.rb | 2 +- lib/chewy/index/import/routine.rb | 6 +----- lib/chewy/search.rb | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/chewy/index.rb b/lib/chewy/index.rb index 3675d7ea9..a7156b42b 100644 --- a/lib/chewy/index.rb +++ b/lib/chewy/index.rb @@ -102,6 +102,11 @@ def es_cluster_host(hosts_name) @hosts_name = hosts_name end + # Calls the delegated method above to Chewy.client + def es_client + client(@hosts_name) + end + # Base name for the index. Uses the default value inferred from the # class name unless redefined. # diff --git a/lib/chewy/index/actions.rb b/lib/chewy/index/actions.rb index 8fa4add89..ce13bd81e 100644 --- a/lib/chewy/index/actions.rb +++ b/lib/chewy/index/actions.rb @@ -12,7 +12,7 @@ module ClassMethods # UsersIndex.exists? #=> true # def exists? - client(@hosts_name).indices.exists(index: index_name) + es_client.indices.exists(index: index_name) end # Creates index and applies mappings and settings. @@ -80,7 +80,6 @@ def delete(suffix = nil) # "The index parameter in the delete index API no longer accepts alias names. # Instead, it accepts only index names (or wildcards which will expand to matching indices)." # https://www.elastic.co/guide/en/elasticsearch/reference/6.8/breaking-changes-6.0.html#_delete_index_api_resolves_indices_expressions_only_against_indices - es_client = client(@hosts_name) index_names = es_client.indices.get_alias(index: index_name(suffix: suffix)).keys result = es_client.indices.delete index: index_names.join(',') Chewy.wait_for_status(es_client) if result @@ -166,13 +165,13 @@ def reset!(suffix = nil, apply_journal: true, journal: false, **import_options) original_index_settings suffixed_name delete if indexes.blank? - client(@hosts_name).indices.update_aliases body: {actions: [ + es_client.indices.update_aliases body: {actions: [ *indexes.map do |index| {remove: {index: index, alias: general_name}} end, {add: {index: suffixed_name, alias: general_name}} ]} - client(@hosts_name).indices.delete index: indexes if indexes.present? + es_client.indices.delete index: indexes if indexes.present? self.journal.apply(start_time, **import_options) if apply_journal result @@ -198,7 +197,7 @@ def clear_cache(args = {index: index_name}) end def reindex(source: index_name, dest: index_name) - client(@hosts_name).reindex( + es_client.reindex( { body: { @@ -216,7 +215,7 @@ def reindex(source: index_name, dest: index_name) # Chewy.client.update_mapping('cities', {properties: {new_field: {type: :text}}}) # def update_mapping(name = index_name, body = root.mappings_hash) - client(@hosts_name).indices.put_mapping( + es_client.indices.put_mapping( index: name, body: body )['acknowledged'] @@ -257,7 +256,7 @@ def original_index_settings(index_name) end def update_settings(index_name, **options) - client(@hosts_name).indices.put_settings index: index_name, body: {index: options[:settings]} + es_client.indices.put_settings index: index_name, body: {index: options[:settings]} end def index_settings(setting_name) diff --git a/lib/chewy/index/aliases.rb b/lib/chewy/index/aliases.rb index c6cc6f7aa..b39f3ec11 100644 --- a/lib/chewy/index/aliases.rb +++ b/lib/chewy/index/aliases.rb @@ -5,14 +5,14 @@ module Aliases module ClassMethods def indexes - indexes = empty_if_not_found { client(@hosts_name).indices.get(index: index_name).keys } - indexes += empty_if_not_found { client(@hosts_name).indices.get_alias(name: index_name).keys } + indexes = empty_if_not_found { es_client.indices.get(index: index_name).keys } + indexes += empty_if_not_found { es_client.indices.get_alias(name: index_name).keys } indexes.compact.uniq end def aliases empty_if_not_found do - client(@hosts_name).indices.get_alias(index: index_name, name: '*').values.flat_map do |aliases| + es_client.indices.get_alias(index: index_name, name: '*').values.flat_map do |aliases| aliases['aliases'].keys end end.compact.uniq diff --git a/lib/chewy/index/import.rb b/lib/chewy/index/import.rb index fac7c52cb..ed9539946 100644 --- a/lib/chewy/index/import.rb +++ b/lib/chewy/index/import.rb @@ -103,7 +103,7 @@ def import!(*args) # @return [Hash] tricky transposed errors hash, empty if everything is fine def bulk(**options) error_items = BulkRequest.new(self, **options).perform(options[:body]) - Chewy.wait_for_status(client(@hosts_name)) + Chewy.wait_for_status(es_client) payload_errors(error_items) end diff --git a/lib/chewy/index/import/routine.rb b/lib/chewy/index/import/routine.rb index 7614a06c7..97721fce6 100644 --- a/lib/chewy/index/import/routine.rb +++ b/lib/chewy/index/import/routine.rb @@ -61,10 +61,6 @@ def initialize(index, **options) @leftovers = [] end - def es_client - @index.client(@index.hosts_name) - end - # Creates the journal index and the corresponding index if necessary. # @return [Object] whatever def create_indexes! @@ -106,7 +102,7 @@ def process(index: [], delete: []) def perform_bulk(body) response = bulk.perform(body) yield response if block_given? - Chewy.wait_for_status(es_client) + Chewy.wait_for_status(@index.es_client) @errors.concat(response) response.blank? end diff --git a/lib/chewy/search.rb b/lib/chewy/search.rb index 36f9b6da5..12359adac 100644 --- a/lib/chewy/search.rb +++ b/lib/chewy/search.rb @@ -49,7 +49,7 @@ def all # @return [Hash] the request result def search_string(query, options = {}) options = options.merge(all.render.slice(:index).merge(q: query)) - Chewy.client(@hosts_name).search(options) + es_client.search(options) end # Delegates methods from the request class to the index class From 1e181eef375ee1a00d73524ac2666ec45dc88d15 Mon Sep 17 00:00:00 2001 From: Amol Patil Date: Fri, 15 Nov 2024 22:47:45 +0530 Subject: [PATCH 6/8] removed temp --- lib/chewy/index/import.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/chewy/index/import.rb b/lib/chewy/index/import.rb index ed9539946..8b4cffed3 100644 --- a/lib/chewy/index/import.rb +++ b/lib/chewy/index/import.rb @@ -128,10 +128,10 @@ def compose(object, crutches = nil, fields: []) private def intercept_import_using_strategy(*args) - options = args.extract_options! - strategy = options.delete(:strategy) + # options = args.extract_options! + # strategy = options.delete(:strategy) - return import_routine(*args) if strategy.blank? + return import_routine(*args) # We should evaluate impact of deep_dup if we pass any specific strategy in the import call # Right now this is always blank in our case, so the code will never reach here From 7d8ef4cf25c2d3b2e84bc9a667a717ed7b4b09fd Mon Sep 17 00:00:00 2001 From: Amol Patil Date: Fri, 15 Nov 2024 22:51:05 +0530 Subject: [PATCH 7/8] temp --- lib/chewy/index/import.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/chewy/index/import.rb b/lib/chewy/index/import.rb index 8b4cffed3..45c168253 100644 --- a/lib/chewy/index/import.rb +++ b/lib/chewy/index/import.rb @@ -128,7 +128,7 @@ def compose(object, crutches = nil, fields: []) private def intercept_import_using_strategy(*args) - # options = args.extract_options! + options = args.extract_options! # strategy = options.delete(:strategy) return import_routine(*args) From a755b093df2d0fd95c5af87f92a1ba7f46eb8658 Mon Sep 17 00:00:00 2001 From: Amol Patil Date: Fri, 15 Nov 2024 23:09:04 +0530 Subject: [PATCH 8/8] removed code for calling custom strategy in import --- lib/chewy/index/import.rb | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/chewy/index/import.rb b/lib/chewy/index/import.rb index 45c168253..5e71dec6e 100644 --- a/lib/chewy/index/import.rb +++ b/lib/chewy/index/import.rb @@ -73,7 +73,7 @@ module ClassMethods # @option options [true, Integer, Hash] parallel enables parallel import processing with the Parallel gem, accepts the number of workers or any Parallel gem acceptable options # @return [true, false] false in case of errors def import(*args) - intercept_import_using_strategy(*args).blank? + import_routine(*args).blank? end # @!method import!(*collection, **options) @@ -84,7 +84,7 @@ def import(*args) # # @raise [Chewy::ImportFailed] in case of errors def import!(*args) - errors = intercept_import_using_strategy(*args) + errors = import_routine(*args) raise Chewy::ImportFailed.new(self, errors) if errors.present? @@ -128,16 +128,15 @@ def compose(object, crutches = nil, fields: []) private def intercept_import_using_strategy(*args) - options = args.extract_options! - # strategy = options.delete(:strategy) - - return import_routine(*args) - # We should evaluate impact of deep_dup if we pass any specific strategy in the import call # Right now this is always blank in our case, so the code will never reach here # Check for our mongo data with invalid attributes, and setters which raise an exception if we want to # call deep_dup args_clone = args.deep_dup + options = args_clone.extract_options! + strategy = options.delete(:strategy) + + return import_routine(*args) if strategy.blank? ids = args_clone.flatten return {} if ids.blank?