From 34efb081a5103909e7be12b85f9681fddde84d04 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Wed, 17 Jul 2019 14:14:05 +0300 Subject: [PATCH 1/2] fix json generator for atomic updates of array fields --- lib/rsolr/document.rb | 3 +++ spec/api/json_spec.rb | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/lib/rsolr/document.rb b/lib/rsolr/document.rb index 84f53697..f92a5fc3 100644 --- a/lib/rsolr/document.rb +++ b/lib/rsolr/document.rb @@ -51,6 +51,9 @@ def as_json if v.length > 1 && v.first.is_a?(Hash) && v.first.key?(:value) v = v.first.merge(value: v.map { |single| single[:value] }) end + if v.length > 1 && v.first.is_a?(Hash) && v.first.key?(:set) + v = [{ set: v.map { |single| single[:set] } }] + end v = v.first if v.length == 1 && field.to_s != CHILD_DOCUMENT_KEY result[field] = v end diff --git a/spec/api/json_spec.rb b/spec/api/json_spec.rb index 22cf068e..b4d63d0b 100644 --- a/spec/api/json_spec.rb +++ b/spec/api/json_spec.rb @@ -158,6 +158,15 @@ def to_h expect(message).to eq [{ id: '1', name: { boost: 3, value: test_values } }] end + it 'creates single field from array values on atomic update' do + test_values = %w[value1 value2] + message = JSON.parse( + generator.add(id: '1') { |doc| doc.add_field(:name, test_values, update: :set) }, + symbolize_names: true + ) + expect(message).to eq [{ id: '1', name: { set: test_values } }] + end + describe '#commit' do it 'generates a commit command' do expect(JSON.parse(generator.commit, symbolize_names: true)).to eq(commit: {}) From 0453b0d82ac9acd749815e5b84499610deb82f71 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Mon, 27 Jan 2020 14:41:52 +0300 Subject: [PATCH 2/2] fix json generator for more atomic operations --- lib/rsolr/document.rb | 14 +++++++---- spec/api/json_spec.rb | 55 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/lib/rsolr/document.rb b/lib/rsolr/document.rb index f92a5fc3..cf57515d 100644 --- a/lib/rsolr/document.rb +++ b/lib/rsolr/document.rb @@ -1,6 +1,7 @@ module RSolr class Document CHILD_DOCUMENT_KEY = '_childDocuments_'.freeze + ATOMIC_MULTI_VALUE_OPERATIONS = %i[set add add-distinct remove] # "attrs" is a hash for setting the "doc" xml attributes # "fields" is an array of Field objects @@ -48,11 +49,14 @@ def add_field(name, values, options = {}) def as_json @fields.group_by(&:name).each_with_object({}) do |(field, values), result| v = values.map(&:as_json) - if v.length > 1 && v.first.is_a?(Hash) && v.first.key?(:value) - v = v.first.merge(value: v.map { |single| single[:value] }) - end - if v.length > 1 && v.first.is_a?(Hash) && v.first.key?(:set) - v = [{ set: v.map { |single| single[:set] } }] + if v.length > 1 && v.first.is_a?(Hash) + if v.first.key?(:value) + v = v.first.merge(value: v.map { |single| single[:value] }) + else + (v.first.keys & ATOMIC_MULTI_VALUE_OPERATIONS).each do |op| + v = [{ op => v.map { |single| single[op] } }] + end + end end v = v.first if v.length == 1 && field.to_s != CHILD_DOCUMENT_KEY result[field] = v diff --git a/spec/api/json_spec.rb b/spec/api/json_spec.rb index b4d63d0b..ab0aebd1 100644 --- a/spec/api/json_spec.rb +++ b/spec/api/json_spec.rb @@ -158,13 +158,54 @@ def to_h expect(message).to eq [{ id: '1', name: { boost: 3, value: test_values } }] end - it 'creates single field from array values on atomic update' do - test_values = %w[value1 value2] - message = JSON.parse( - generator.add(id: '1') { |doc| doc.add_field(:name, test_values, update: :set) }, - symbolize_names: true - ) - expect(message).to eq [{ id: '1', name: { set: test_values } }] + context 'for atomic updates with arrays' do + let(:test_values) { %w[value1 value2] } + + it 'creates single field from array values on SET' do + expect( + JSON.parse( + generator.add(id: 'set-id') { |doc| doc.add_field(:name, test_values, update: :set) }, + symbolize_names: true + ) + ).to eq [{ id: 'set-id', name: { set: test_values } }] + end + + it 'creates single field from array values on ADD' do + expect( + JSON.parse( + generator.add(id: 'add-id') { |doc| doc.add_field(:name, test_values, update: :add) }, + symbolize_names: true + ) + ).to eq [{ id: 'add-id', name: { add: test_values } }] + end + + it 'creates single field from array values on ADD-DISTINCT' do + expect( + JSON.parse( + generator.add(id: 'add-distinct-id') { |doc| doc.add_field(:name, test_values, update: :'add-distinct') }, + symbolize_names: true + ) + ).to eq [{ id: 'add-distinct-id', name: { 'add-distinct': test_values } }] + end + + it 'creates single field from array values on REMOVE' do + expect( + JSON.parse( + generator.add(id: 'remove-id') { |doc| doc.add_field(:name, test_values, update: :remove) }, + symbolize_names: true + ) + ).to eq [{ id: 'remove-id', name: { remove: test_values } }] + end + + it 'creates single field from array values for child document update' do + test_nested_values = [{id: 1, name: 'value1'}, {id: 1, name: 'value2'}] + expect( + JSON.parse( + generator.add(id: 'set-id') { |doc| doc.add_field(:child_documents, test_nested_values, update: :set) }, + symbolize_names: true + ) + ).to eq [{ id: 'set-id', child_documents: { set: test_nested_values } }] + end end describe '#commit' do