diff --git a/lib/esse/index/documents.rb b/lib/esse/index/documents.rb index fe61f7f..74f365c 100644 --- a/lib/esse/index/documents.rb +++ b/lib/esse/index/documents.rb @@ -236,6 +236,20 @@ def import(*repo_types, context: {}, eager_include_document_attributes: false, l count end + # Update documents by query + # + # @param options [Hash] Hash of paramenters that will be passed along to elasticsearch request + # @option [String, nil] :suffix The index suffix. Defaults to the nil. + # + # @return [Hash] The elasticsearch response hash + def update_by_query(suffix: nil, **options) + definition = { + index: index_name(suffix: suffix), + }.merge(options) + cluster.may_update_type!(definition) + cluster.api.update_by_query(**definition) + end + protected def document?(doc) diff --git a/spec/esse/integrations/elasticsearch-6/index/documents_update_by_query_spec.rb b/spec/esse/integrations/elasticsearch-6/index/documents_update_by_query_spec.rb new file mode 100644 index 0000000..cbc0485 --- /dev/null +++ b/spec/esse/integrations/elasticsearch-6/index/documents_update_by_query_spec.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'support/shared_examples/index_documents_update_by_query' + +stack_describe 'elasticsearch', '6.x', Esse::Index, '.update_by_query' do + include_examples 'index.update_by_query' +end diff --git a/spec/esse/integrations/elasticsearch-7/index/documents_update_by_query_spec.rb b/spec/esse/integrations/elasticsearch-7/index/documents_update_by_query_spec.rb new file mode 100644 index 0000000..37759c3 --- /dev/null +++ b/spec/esse/integrations/elasticsearch-7/index/documents_update_by_query_spec.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'support/shared_examples/index_documents_update_by_query' + +stack_describe 'elasticsearch', '7.x', Esse::Index, '.update_by_query' do + include_examples 'index.update_by_query' +end diff --git a/spec/esse/integrations/elasticsearch-8/indices/documents_update_by_query_spec.rb b/spec/esse/integrations/elasticsearch-8/indices/documents_update_by_query_spec.rb new file mode 100644 index 0000000..ba1c4f6 --- /dev/null +++ b/spec/esse/integrations/elasticsearch-8/indices/documents_update_by_query_spec.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'support/shared_examples/index_documents_update_by_query' + +stack_describe 'elasticsearch', '8.x', Esse::Index, '.update_by_query' do + include_examples 'index.update_by_query' +end diff --git a/spec/support/shared_examples/index_documents_update_by_query.rb b/spec/support/shared_examples/index_documents_update_by_query.rb new file mode 100644 index 0000000..6fb44eb --- /dev/null +++ b/spec/support/shared_examples/index_documents_update_by_query.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'index.update_by_query' do |doc_type: false| + include_context 'with venues index definition' + + let(:params) do + doc_type ? { type: 'venue' } : {} + end + let(:doc_params) do + doc_type ? { _type: 'venue' } : {} + end + let(:index_suffix) { SecureRandom.hex(8) } + let(:body) { { script: { source: 'ctx._source.title = "foo"' }, query: { match_all: {} } } } + + it 'raises an Esse::Transport::ReadonlyClusterError exception when the cluster is readonly' do + es_client do |client, _conf, cluster| + cluster.warm_up! + expect(client).not_to receive(:perform_request) + cluster.readonly = true + expect { + VenuesIndex.update_by_query(body: body, **params) + }.to raise_error(Esse::Transport::ReadonlyClusterError) + end + end + + it 'raises an Esse::Transport::ServerError exception when api throws an error' do + es_client do |client, _conf, cluster| + expect { + VenuesIndex.update_by_query(body: body, **params) + }.to raise_error(Esse::Transport::NotFoundError) + end + end + + it 'updates the documents in the aliased index' do + es_client do |client, _conf, cluster| + VenuesIndex.create_index(alias: true, suffix: index_suffix) + VenuesIndex.import(refresh: true, suffix: index_suffix, **params) + + resp = nil + expect { + resp = VenuesIndex.update_by_query(body: body, **params) + }.not_to raise_error + expect(resp['total']).to eq(total_venues) + expect(resp['updated']).to eq(total_venues) + end + end + + it 'updates the documents in the unaliased index' do + es_client do |client, _conf, cluster| + VenuesIndex.create_index(alias: false, suffix: index_suffix) + VenuesIndex.import(refresh: true, suffix: index_suffix, **params) + + resp = nil + expect { + resp = VenuesIndex.update_by_query(body: body, suffix: index_suffix, **params) + }.not_to raise_error + expect(resp['total']).to eq(total_venues) + expect(resp['updated']).to eq(total_venues) + end + end +end