From 14d7ced75a4fb48d71fde20c536205567d8b19a3 Mon Sep 17 00:00:00 2001 From: Emily Giurleo Date: Tue, 28 Jul 2020 17:26:24 -0400 Subject: [PATCH 1/4] support the hidden option on index creation --- lib/mongo/index/view.rb | 3 ++ spec/mongo/index/view_spec.rb | 70 +++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/lib/mongo/index/view.rb b/lib/mongo/index/view.rb index 5774c253b5..5d8fa43588 100644 --- a/lib/mongo/index/view.rb +++ b/lib/mongo/index/view.rb @@ -120,6 +120,9 @@ def drop_all # a geo index. # @option options [ Hash ] :partial_filter_expression Specify a filter for a partial # index. + # @option options [ Boolean ] :hidden When :hidden is true, this index will + # exist on the collection but not be used by the query planner when + # executing operations. # @option options [ String | Integer ] :commit_quorum Specify how many # data-bearing members of a replica set, including the primary, must # complete the index builds successfully before the primary marks diff --git a/spec/mongo/index/view_spec.rb b/spec/mongo/index/view_spec.rb index a854f85e67..9143a29000 100644 --- a/spec/mongo/index/view_spec.rb +++ b/spec/mongo/index/view_spec.rb @@ -773,6 +773,76 @@ end end + context 'when providing hint option' do + let(:subscriber) { EventSubscriber.new } + + let(:client) do + authorized_client.tap do |client| + client.subscribe(Mongo::Monitoring::COMMAND, subscriber) + end + end + + let(:authorized_collection) { client['view-subscribed'] } + + let(:indexes) do + authorized_collection.indexes.get('x_1') + end + + let(:events) do + subscriber.command_started_events('createIndexes') + end + + context 'on server versions < 4.4' do + max_server_fcv '4.2' + + it 'raises an exception' do + expect do + view.create_one({ 'x' => 1 }, { hidden: true }) + end.to raise_error(/The field 'hidden' is not valid for an index specification/) + end + end + + context 'on server versions >= 4.4' do + min_server_fcv '4.4' + + context 'when hidden is true' do + let!(:result) { view.create_one({ 'x' => 1 }, { hidden: true }) } + + it 'returns ok' do + expect(result).to be_successful + end + + it 'creates an index' do + expect(indexes).to_not be_nil + end + + it 'passes the hint option to the server' do + expect(events.length).to eq(1) + command = events.first.command + expect(command['indexes'].first['hidden']).to be true + end + end + + context 'when hidden is false' do + let!(:result) { view.create_one({ 'x' => 1 }, { hidden: false }) } + + it 'returns ok' do + expect(result).to be_successful + end + + it 'creates an index' do + expect(indexes).to_not be_nil + end + + it 'passes the hint option to the server' do + expect(events.length).to eq(1) + command = events.first.command + expect(command['indexes'].first['hidden']).to be false + end + end + end + end + context 'when providing commit_quorum option' do require_topology :replica_set, :sharded context 'on server versions >= 4.4' do From 89eeb1311c10626b7ec926c26cd67137b117a710 Mon Sep 17 00:00:00 2001 From: Emily Giurleo Date: Wed, 29 Jul 2020 09:14:45 -0400 Subject: [PATCH 2/4] added create_one and create_many tests to the index view spec --- spec/mongo/index/view_spec.rb | 94 ++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 30 deletions(-) diff --git a/spec/mongo/index/view_spec.rb b/spec/mongo/index/view_spec.rb index 9143a29000..2d649999a9 100644 --- a/spec/mongo/index/view_spec.rb +++ b/spec/mongo/index/view_spec.rb @@ -325,6 +325,60 @@ end end + context 'when hidden is specified' do + let(:index) { view.get('with_hidden_1') } + + context 'on server versions >= 4.4' do + min_server_fcv '4.4' + + context 'when hidden is true' do + let!(:result) do + view.create_many({ key: { with_hidden: 1 }, hidden: true }) + end + + it 'returns ok' do + expect(result).to be_successful + end + + it 'creates an index' do + expect(index).to_not be_nil + end + + it 'applies the hidden option to the index' do + expect(index['hidden']).to be true + end + end + + context 'when hidden is false' do + let!(:result) do + view.create_many({ key: { with_hidden: 1 }, hidden: false }) + end + + it 'returns ok' do + expect(result).to be_successful + end + + it 'creates an index' do + expect(index).to_not be_nil + end + + it 'does not apply the hidden option to the index' do + expect(index['hidden']).to be_nil + end + end + end + + context 'on server versions < 4.4' do + max_server_fcv '4.2' + + it 'raises an exception' do + expect do + view.create_many({ key: { with_hidden: 1 }, hidden: true }) + end.to raise_error(/The field 'hidden' is not valid for an index specification/) + end + end + end + context 'when collation is specified' do min_server_fcv '3.4' @@ -774,30 +828,14 @@ end context 'when providing hint option' do - let(:subscriber) { EventSubscriber.new } - - let(:client) do - authorized_client.tap do |client| - client.subscribe(Mongo::Monitoring::COMMAND, subscriber) - end - end - - let(:authorized_collection) { client['view-subscribed'] } - - let(:indexes) do - authorized_collection.indexes.get('x_1') - end - - let(:events) do - subscriber.command_started_events('createIndexes') - end + let(:index) { view.get('with_hidden_1') } context 'on server versions < 4.4' do max_server_fcv '4.2' it 'raises an exception' do expect do - view.create_one({ 'x' => 1 }, { hidden: true }) + view.create_one({ 'with_hidden' => 1 }, { hidden: true }) end.to raise_error(/The field 'hidden' is not valid for an index specification/) end end @@ -806,38 +844,34 @@ min_server_fcv '4.4' context 'when hidden is true' do - let!(:result) { view.create_one({ 'x' => 1 }, { hidden: true }) } + let!(:result) { view.create_one({ 'with_hidden' => 1 }, { hidden: true }) } it 'returns ok' do expect(result).to be_successful end it 'creates an index' do - expect(indexes).to_not be_nil + expect(index).to_not be_nil end - it 'passes the hint option to the server' do - expect(events.length).to eq(1) - command = events.first.command - expect(command['indexes'].first['hidden']).to be true + it 'applies the hidden option to the index' do + expect(index['hidden']).to be true end end context 'when hidden is false' do - let!(:result) { view.create_one({ 'x' => 1 }, { hidden: false }) } + let!(:result) { view.create_one({ 'with_hidden' => 1 }, { hidden: false }) } it 'returns ok' do expect(result).to be_successful end it 'creates an index' do - expect(indexes).to_not be_nil + expect(index).to_not be_nil end - it 'passes the hint option to the server' do - expect(events.length).to eq(1) - command = events.first.command - expect(command['indexes'].first['hidden']).to be false + it 'does not apply the hidden option to the index' do + expect(index['hidden']).to be_nil end end end From d79f17866be957d6281dda91fac8a04ef3f3fea3 Mon Sep 17 00:00:00 2001 From: Emily Giurleo Date: Wed, 29 Jul 2020 09:21:14 -0400 Subject: [PATCH 3/4] added information to the index tutorial --- docs/tutorials/ruby-driver-indexing.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/tutorials/ruby-driver-indexing.txt b/docs/tutorials/ruby-driver-indexing.txt index d187c35014..0a29b768cb 100644 --- a/docs/tutorials/ruby-driver-indexing.txt +++ b/docs/tutorials/ruby-driver-indexing.txt @@ -95,6 +95,9 @@ when creating indexes. These options mirror the options supported by the - The number of units within which to group the location values in a geo haystack index. * - ``:partial_filter_expression`` - A filter for a partial index. + * - ``:hidden`` + - A Boolean specifying whether the index should be hidden; a hidden index + is one that exists on the collection but will not be used by the query planner. The :commit_quorum option ------------------------- From 4b55dd7bb923ffdba5511da36f77b1e79a399d66 Mon Sep 17 00:00:00 2001 From: Emily Giurleo Date: Wed, 29 Jul 2020 10:40:04 -0400 Subject: [PATCH 4/4] fix server versions on tests --- spec/mongo/index/view_spec.rb | 66 ++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/spec/mongo/index/view_spec.rb b/spec/mongo/index/view_spec.rb index 2d649999a9..c68ce04705 100644 --- a/spec/mongo/index/view_spec.rb +++ b/spec/mongo/index/view_spec.rb @@ -328,6 +328,37 @@ context 'when hidden is specified' do let(:index) { view.get('with_hidden_1') } + context 'on server versions <= 3.2' do + # DRIVERS-1220 Server versions 3.2 and older do not perform any option + # checking on index creation. The server will allow the user to create + # the index with the hidden option, but the server does not support this + # option and will not use it. + max_server_fcv '3.2' + + let!(:result) do + view.create_many({ key: { with_hidden: 1 }, hidden: true }) + end + + it 'returns ok' do + expect(result).to be_successful + end + + it 'creates an index' do + expect(index).to_not be_nil + end + end + + context 'on server versions between 3.4 and 4.2' do + max_server_fcv '4.2' + min_server_fcv '3.4' + + it 'raises an exception' do + expect do + view.create_many({ key: { with_hidden: 1 }, hidden: true }) + end.to raise_error(/The field 'hidden' is not valid for an index specification/) + end + end + context 'on server versions >= 4.4' do min_server_fcv '4.4' @@ -367,16 +398,6 @@ end end end - - context 'on server versions < 4.4' do - max_server_fcv '4.2' - - it 'raises an exception' do - expect do - view.create_many({ key: { with_hidden: 1 }, hidden: true }) - end.to raise_error(/The field 'hidden' is not valid for an index specification/) - end - end end context 'when collation is specified' do @@ -827,11 +848,32 @@ end end - context 'when providing hint option' do + context 'when providing hidden option' do let(:index) { view.get('with_hidden_1') } - context 'on server versions < 4.4' do + context 'on server versions <= 3.2' do + # DRIVERS-1220 Server versions 3.2 and older do not perform any option + # checking on index creation. The server will allow the user to create + # the index with the hidden option, but the server does not support this + # option and will not use it. + max_server_fcv '3.2' + + let!(:result) do + view.create_one({ 'with_hidden' => 1 }, { hidden: true }) + end + + it 'returns ok' do + expect(result).to be_successful + end + + it 'creates an index' do + expect(index).to_not be_nil + end + end + + context 'on server versions between 3.4 and 4.2' do max_server_fcv '4.2' + min_server_fcv '3.4' it 'raises an exception' do expect do