mongo 2.19.1 → 2.19.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/mongo/collection/view/iterable.rb +15 -0
  4. data/lib/mongo/collection/view.rb +1 -0
  5. data/lib/mongo/collection.rb +23 -1
  6. data/lib/mongo/operation/create_search_indexes/op_msg.rb +31 -0
  7. data/lib/mongo/operation/create_search_indexes.rb +15 -0
  8. data/lib/mongo/operation/drop_search_index/op_msg.rb +33 -0
  9. data/lib/mongo/operation/drop_search_index.rb +15 -0
  10. data/lib/mongo/operation/shared/specifiable.rb +7 -0
  11. data/lib/mongo/operation/update_search_index/op_msg.rb +34 -0
  12. data/lib/mongo/operation/update_search_index.rb +15 -0
  13. data/lib/mongo/operation.rb +3 -0
  14. data/lib/mongo/search_index/view.rb +232 -0
  15. data/lib/mongo/version.rb +1 -1
  16. data/lib/mongo.rb +1 -0
  17. data/spec/atlas/atlas_connectivity_spec.rb +1 -5
  18. data/spec/atlas/operations_spec.rb +1 -5
  19. data/spec/integration/find_options_spec.rb +227 -0
  20. data/spec/integration/search_indexes_prose_spec.rb +168 -0
  21. data/spec/lite_spec_helper.rb +32 -10
  22. data/spec/runners/unified/search_index_operations.rb +63 -0
  23. data/spec/runners/unified/test.rb +3 -1
  24. data/spec/spec_helper.rb +1 -1
  25. data/spec/spec_tests/data/index_management/createSearchIndex.yml +62 -0
  26. data/spec/spec_tests/data/index_management/createSearchIndexes.yml +83 -0
  27. data/spec/spec_tests/data/index_management/dropSearchIndex.yml +42 -0
  28. data/spec/spec_tests/data/index_management/listSearchIndexes.yml +85 -0
  29. data/spec/spec_tests/data/index_management/updateSearchIndex.yml +45 -0
  30. data/spec/spec_tests/index_management_unified_spec.rb +13 -0
  31. data/spec/support/faas/app/aws_lambda/mongodb/Gemfile.lock +19 -0
  32. data/spec/support/spec_config.rb +5 -0
  33. data.tar.gz.sig +0 -0
  34. metadata +1277 -1250
  35. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 624436394458300bf64df3d0b424b75ea03746b8f1a53987c18be7e33f5d4f74
4
- data.tar.gz: da54416a85f4a3e6318ec6833ae14997a864a5d490c8e0fe451aa2c0acd4fe71
3
+ metadata.gz: '0916a285c62c2e70c94532ca2ed61af6bfcb1ead971a2be825aefbde560209c3'
4
+ data.tar.gz: a9db987bb6f1e2b7e9882c86472bc2c8b10eca0d4bdca9de2a37968de086d8f3
5
5
  SHA512:
6
- metadata.gz: a4c15fae18c57a1c33f45cde07bf325f7d2c45f2fafdf99d521900d0277feb395f0947d422939eda0572d7f0a17819a94ba1e906b1939d83e1aaefc4b662b2a0
7
- data.tar.gz: e0cc5f507b02f8e787c1793b8cb708cd17090505e6ac239db7ed02cd54367d9a0079a6f64f23bf2d661820c6bbbc2df82467a15b90e884a8d9bee88a84065abb
6
+ metadata.gz: ab6a8e7e008174f346f1acd96bb073a39cd4fbdd2a70e44f63f8dcdc421c4d38ba9277cc9c50099c944599886e53230597bdab8bd4c861de29af2bd66dd2be76
7
+ data.tar.gz: 8fe9155b17bbb9b57021eabd7e2211baf2cb0002b211900e8564e0b1c2f9e894bf726a037b1e8b72e6dd55251edefe1e81fd8c3ea61aacd0fd5d7eb76cbc4163
checksums.yaml.gz.sig CHANGED
Binary file
@@ -185,6 +185,8 @@ module Mongo
185
185
  collection.client.log_warn("The :oplog_replay option is deprecated and ignored by MongoDB 4.4 and later")
186
186
  end
187
187
 
188
+ maybe_set_tailable_options(spec)
189
+
188
190
  if explained?
189
191
  spec[:explain] = options[:explain]
190
192
  Operation::Explain.new(spec)
@@ -200,6 +202,19 @@ module Mongo
200
202
  def use_query_cache?
201
203
  QueryCache.enabled? && !collection.system_collection?
202
204
  end
205
+
206
+ # Add tailable cusror options to the command specifiction if needed.
207
+ #
208
+ # @param [ Hash ] spec The command specification.
209
+ def maybe_set_tailable_options(spec)
210
+ case cursor_type
211
+ when :tailable
212
+ spec[:tailable] = true
213
+ when :tailable_await
214
+ spec[:tailable] = true
215
+ spec[:await_data] = true
216
+ end
217
+ end
203
218
  end
204
219
  end
205
220
  end
@@ -127,6 +127,7 @@ module Mongo
127
127
  # return in each response from MongoDB.
128
128
  # @option options [ Hash ] :collation The collation to use.
129
129
  # @option options [ String ] :comment Associate a comment with the query.
130
+ # @option options [ :tailable, :tailable_await ] :cursor_type The type of cursor to use.
130
131
  # @option options [ Hash ] :explain Execute an explain with the provided
131
132
  # explain options (known options are :verbose and :verbosity) rather
132
133
  # than a find.
@@ -725,13 +725,35 @@ module Mongo
725
725
  #
726
726
  # @option options [ Session ] :session The session to use.
727
727
  #
728
- # @return [ View::Index ] The index view.
728
+ # @return [ Index::View ] The index view.
729
729
  #
730
730
  # @since 2.0.0
731
731
  def indexes(options = {})
732
732
  Index::View.new(self, options)
733
733
  end
734
734
 
735
+ # Get a view of all search indexes for this collection. Can be iterated or
736
+ # operated on directly. If id or name are given, the iterator will return
737
+ # only the indicated index. For all other operations, id and name are
738
+ # ignored.
739
+ #
740
+ # @note Only one of id or name may be given; it is an error to specify both,
741
+ # although both may be omitted safely.
742
+ #
743
+ # @param [ Hash ] options The options to use to configure the view.
744
+ #
745
+ # @option options [ String ] :id The id of the specific index to query (optional)
746
+ # @option options [ String ] :name The name of the specific index to query (optional)
747
+ # @option options [ Hash ] :aggregate The options hash to pass to the
748
+ # aggregate command (optional)
749
+ #
750
+ # @return [ SearchIndex::View ] The search index view.
751
+ #
752
+ # @since 2.0.0
753
+ def search_indexes(options = {})
754
+ SearchIndex::View.new(self, options)
755
+ end
756
+
735
757
  # Get a pretty printed string inspection for the collection.
736
758
  #
737
759
  # @example Inspect the collection.
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongo
4
+ module Operation
5
+ class CreateSearchIndexes
6
+ # A MongoDB createSearchIndexes operation sent as an op message.
7
+ #
8
+ # @api private
9
+ class OpMsg < OpMsgBase
10
+ include ExecutableTransactionLabel
11
+
12
+ private
13
+
14
+ # Returns the command to send to the database, describing the
15
+ # desired createSearchIndexes operation.
16
+ #
17
+ # @param [ Mongo::Server ] _server the server that will receive the
18
+ # command
19
+ #
20
+ # @return [ Hash ] the selector
21
+ def selector(_server)
22
+ {
23
+ createSearchIndexes: coll_name,
24
+ :$db => db_name,
25
+ indexes: indexes,
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mongo/operation/create_search_indexes/op_msg'
4
+
5
+ module Mongo
6
+ module Operation
7
+ # A MongoDB createSearchIndexes command operation.
8
+ #
9
+ # @api private
10
+ class CreateSearchIndexes
11
+ include Specifiable
12
+ include OpMsgExecutable
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongo
4
+ module Operation
5
+ class DropSearchIndex
6
+ # A MongoDB createSearchIndexes operation sent as an op message.
7
+ #
8
+ # @api private
9
+ class OpMsg < OpMsgBase
10
+ include ExecutableTransactionLabel
11
+
12
+ private
13
+
14
+ # Returns the command to send to the database, describing the
15
+ # desired dropSearchIndex operation.
16
+ #
17
+ # @param [ Mongo::Server ] _server the server that will receive the
18
+ # command
19
+ #
20
+ # @return [ Hash ] the selector
21
+ def selector(_server)
22
+ {
23
+ dropSearchIndex: coll_name,
24
+ :$db => db_name,
25
+ }.tap do |sel|
26
+ sel[:id] = index_id if index_id
27
+ sel[:name] = index_name if index_name
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mongo/operation/drop_search_index/op_msg'
4
+
5
+ module Mongo
6
+ module Operation
7
+ # A MongoDB dropSearchIndex command operation.
8
+ #
9
+ # @api private
10
+ class DropSearchIndex
11
+ include Specifiable
12
+ include OpMsgExecutable
13
+ end
14
+ end
15
+ end
@@ -260,6 +260,13 @@ module Mongo
260
260
  spec[INDEX]
261
261
  end
262
262
 
263
+ # Get the index id from the spec.
264
+ #
265
+ # @return [ String ] The index id.
266
+ def index_id
267
+ spec[:index_id]
268
+ end
269
+
263
270
  # Get the index name from the spec.
264
271
  #
265
272
  # @example Get the index name.
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongo
4
+ module Operation
5
+ class UpdateSearchIndex
6
+ # A MongoDB updateSearchIndex operation sent as an op message.
7
+ #
8
+ # @api private
9
+ class OpMsg < OpMsgBase
10
+ include ExecutableTransactionLabel
11
+
12
+ private
13
+
14
+ # Returns the command to send to the database, describing the
15
+ # desired updateSearchIndex operation.
16
+ #
17
+ # @param [ Mongo::Server ] _server the server that will receive the
18
+ # command
19
+ #
20
+ # @return [ Hash ] the selector
21
+ def selector(_server)
22
+ {
23
+ updateSearchIndex: coll_name,
24
+ :$db => db_name,
25
+ definition: index,
26
+ }.tap do |sel|
27
+ sel[:id] = index_id if index_id
28
+ sel[:name] = index_name if index_name
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mongo/operation/update_search_index/op_msg'
4
+
5
+ module Mongo
6
+ module Operation
7
+ # A MongoDB updateSearchIndex command operation.
8
+ #
9
+ # @api private
10
+ class UpdateSearchIndex
11
+ include Specifiable
12
+ include OpMsgExecutable
13
+ end
14
+ end
15
+ end
@@ -51,6 +51,9 @@ require 'mongo/operation/update_user'
51
51
  require 'mongo/operation/remove_user'
52
52
  require 'mongo/operation/create_index'
53
53
  require 'mongo/operation/drop_index'
54
+ require 'mongo/operation/create_search_indexes'
55
+ require 'mongo/operation/drop_search_index'
56
+ require 'mongo/operation/update_search_index'
54
57
 
55
58
  module Mongo
56
59
 
@@ -0,0 +1,232 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongo
4
+ module SearchIndex
5
+ # A class representing a view of search indexes.
6
+ class View
7
+ include Enumerable
8
+ include Retryable
9
+ include Collection::Helpers
10
+
11
+ # @return [ Mongo::Collection ] the collection this view belongs to
12
+ attr_reader :collection
13
+
14
+ # @return [ nil | String ] the index id to query
15
+ attr_reader :requested_index_id
16
+
17
+ # @return [ nil | String ] the index name to query
18
+ attr_reader :requested_index_name
19
+
20
+ # @return [ Hash ] the options hash to use for the aggregate command
21
+ # when querying the available indexes.
22
+ attr_reader :aggregate_options
23
+
24
+ # Create the new search index view.
25
+ #
26
+ # @param [ Collection ] collection The collection.
27
+ # @param [ Hash ] options The options that configure the behavior of the view.
28
+ #
29
+ # @option options [ String ] :id The specific index id to query (optional)
30
+ # @option options [ String ] :name The name of the specific index to query (optional)
31
+ # @option options [ Hash ] :aggregate The options hash to send to the
32
+ # aggregate command when querying the available indexes.
33
+ def initialize(collection, options = {})
34
+ @collection = collection
35
+ @requested_index_id = options[:id]
36
+ @requested_index_name = options[:name]
37
+ @aggregate_options = options[:aggregate] || {}
38
+
39
+ return if @aggregate_options.is_a?(Hash)
40
+
41
+ raise ArgumentError, "The :aggregate option must be a Hash (got a #{@aggregate_options.class})"
42
+ end
43
+
44
+ # Create a single search index with the given definition. If the name is
45
+ # provided, the new index will be given that name.
46
+ #
47
+ # @param [ Hash ] definition The definition of the search index.
48
+ # @param [ nil | String ] name The name to give the new search index.
49
+ #
50
+ # @return [ String ] the name of the new search index.
51
+ def create_one(definition, name: nil)
52
+ create_many([ { name: name, definition: definition } ]).first
53
+ end
54
+
55
+ # Create multiple search indexes with a single command.
56
+ #
57
+ # @param [ Array<Hash> ] indexes The description of the indexes to
58
+ # create. Each element of the list must be a hash with a definition
59
+ # key, and an optional name key.
60
+ #
61
+ # @return [ Array<String> ] the names of the new search indexes.
62
+ def create_many(indexes)
63
+ spec = spec_with(indexes: indexes.map { |v| validate_search_index!(v) })
64
+ result = Operation::CreateSearchIndexes.new(spec).execute(next_primary, context: execution_context)
65
+ result.first['indexesCreated'].map { |idx| idx['name'] }
66
+ end
67
+
68
+ # Drop the search index with the given id, or name. One or the other must
69
+ # be specified, but not both.
70
+ #
71
+ # @param [ String ] id the id of the index to drop
72
+ # @param [ String ] name the name of the index to drop
73
+ #
74
+ # @return [ Mongo::Operation::Result | false ] the result of the
75
+ # operation, or false if the given index does not exist.
76
+ def drop_one(id: nil, name: nil)
77
+ validate_id_or_name!(id, name)
78
+
79
+ spec = spec_with(index_id: id, index_name: name)
80
+ op = Operation::DropSearchIndex.new(spec)
81
+
82
+ # per the spec:
83
+ # Drivers MUST suppress NamespaceNotFound errors for the
84
+ # ``dropSearchIndex`` helper. Drop operations should be idempotent.
85
+ do_drop(op, nil, execution_context)
86
+ end
87
+
88
+ # Iterate over the search indexes.
89
+ #
90
+ # @param [ Proc ] block if given, each search index will be yieleded to
91
+ # the block.
92
+ #
93
+ # @return [ self | Enumerator ] if a block is given, self is returned.
94
+ # Otherwise, an enumerator will be returned.
95
+ def each(&block)
96
+ @result ||= begin
97
+ spec = {}.tap do |s|
98
+ s[:id] = requested_index_id if requested_index_id
99
+ s[:name] = requested_index_name if requested_index_name
100
+ end
101
+
102
+ collection.aggregate(
103
+ [ { '$listSearchIndexes' => spec } ],
104
+ aggregate_options
105
+ )
106
+ end
107
+
108
+ return @result.to_enum unless block
109
+
110
+ @result.each(&block)
111
+ self
112
+ end
113
+
114
+ # Update the search index with the given id or name. One or the other
115
+ # must be provided, but not both.
116
+ #
117
+ # @param [ Hash ] definition the definition to replace the given search
118
+ # index with.
119
+ # @param [ nil | String ] id the id of the search index to update
120
+ # @param [ nil | String ] name the name of the search index to update
121
+ #
122
+ # @return [ Mongo::Operation::Result ] the result of the operation
123
+ def update_one(definition, id: nil, name: nil)
124
+ validate_id_or_name!(id, name)
125
+
126
+ spec = spec_with(index_id: id, index_name: name, index: definition)
127
+ Operation::UpdateSearchIndex.new(spec).execute(next_primary, context: execution_context)
128
+ end
129
+
130
+ # The following methods are to make the view act more like an array,
131
+ # without having to explicitly make it an array...
132
+
133
+ # Queries whether the search index enumerable is empty.
134
+ #
135
+ # @return [ true | false ] whether the enumerable is empty or not.
136
+ def empty?
137
+ count.zero?
138
+ end
139
+
140
+ private
141
+
142
+ # A helper method for building the specification document with certain
143
+ # values pre-populated.
144
+ #
145
+ # @param [ Hash ] extras the values to put into the specification
146
+ #
147
+ # @return [ Hash ] the specification document
148
+ def spec_with(extras)
149
+ {
150
+ coll_name: collection.name,
151
+ db_name: collection.database.name,
152
+ }.merge(extras)
153
+ end
154
+
155
+ # A helper method for retrieving the primary server from the cluster.
156
+ #
157
+ # @return [ Mongo::Server ] the server to use
158
+ def next_primary(ping = nil, session = nil)
159
+ collection.cluster.next_primary(ping, session)
160
+ end
161
+
162
+ # A helper method for constructing a new operation context for executing
163
+ # an operation.
164
+ #
165
+ # @return [ Mongo::Operation::Context ] the operation context
166
+ def execution_context
167
+ Operation::Context.new(client: collection.client)
168
+ end
169
+
170
+ # Validates the given id and name, ensuring that exactly one of them
171
+ # is non-nil.
172
+ #
173
+ # @param [ nil | String ] id the id to validate
174
+ # @param [ nil | String ] name the name to validate
175
+ #
176
+ # @raise [ ArgumentError ] if neither or both arguments are nil
177
+ def validate_id_or_name!(id, name)
178
+ return unless (id.nil? && name.nil?) || (!id.nil? && !name.nil?)
179
+
180
+ raise ArgumentError, 'exactly one of id or name must be specified'
181
+ end
182
+
183
+ # Validates the given search index document, ensuring that it has no
184
+ # extra keys, and that the name and definition are valid.
185
+ #
186
+ # @param [ Hash ] doc the document to validate
187
+ #
188
+ # @raise [ ArgumentError ] if the document is invalid.
189
+ def validate_search_index!(doc)
190
+ validate_search_index_keys!(doc.keys)
191
+ validate_search_index_name!(doc[:name] || doc['name'])
192
+ validate_search_index_definition!(doc[:definition] || doc['definition'])
193
+ doc
194
+ end
195
+
196
+ # Validates the keys of a search index document, ensuring that
197
+ # they are all valid.
198
+ #
199
+ # @param [ Array<String | Hash> ] keys the keys of a search index document
200
+ #
201
+ # @raise [ ArgumentError ] if the list contains any invalid keys
202
+ def validate_search_index_keys!(keys)
203
+ extras = keys - [ 'name', 'definition', :name, :definition ]
204
+
205
+ raise ArgumentError, "invalid keys in search index creation: #{extras.inspect}" if extras.any?
206
+ end
207
+
208
+ # Validates the name of a search index, ensuring that it is either a
209
+ # String or nil.
210
+ #
211
+ # @param [ nil | String ] name the name of a search index
212
+ #
213
+ # @raise [ ArgumentError ] if the name is not valid
214
+ def validate_search_index_name!(name)
215
+ return if name.nil? || name.is_a?(String)
216
+
217
+ raise ArgumentError, "search index name must be nil or a string (got #{name.inspect})"
218
+ end
219
+
220
+ # Validates the definition of a search index.
221
+ #
222
+ # @param [ Hash ] definition the definition of a search index
223
+ #
224
+ # @raise [ ArgumentError ] if the definition is not valid
225
+ def validate_search_index_definition!(definition)
226
+ return if definition.is_a?(Hash)
227
+
228
+ raise ArgumentError, "search index definition must be a Hash (got #{definition.inspect})"
229
+ end
230
+ end
231
+ end
232
+ end
data/lib/mongo/version.rb CHANGED
@@ -20,5 +20,5 @@ module Mongo
20
20
  # The current version of the driver.
21
21
  #
22
22
  # @since 2.0.0
23
- VERSION = '2.19.1'.freeze
23
+ VERSION = '2.19.3'.freeze
24
24
  end
data/lib/mongo.rb CHANGED
@@ -64,6 +64,7 @@ require 'mongo/client_encryption'
64
64
  require 'mongo/dbref'
65
65
  require 'mongo/grid'
66
66
  require 'mongo/index'
67
+ require 'mongo/search_index/view'
67
68
  require 'mongo/lint'
68
69
  require 'mongo/query_cache'
69
70
  require 'mongo/server'
@@ -7,11 +7,7 @@ describe 'Atlas connectivity' do
7
7
  let(:uri) { ENV['ATLAS_URI'] }
8
8
  let(:client) { Mongo::Client.new(uri) }
9
9
 
10
- before do
11
- if uri.nil?
12
- skip "ATLAS_URI not set in environment"
13
- end
14
- end
10
+ require_atlas
15
11
 
16
12
  describe 'connection to Atlas' do
17
13
  it 'runs ismaster successfully' do
@@ -7,11 +7,7 @@ describe 'Operations' do
7
7
  let(:uri) { ENV['ATLAS_URI'] }
8
8
  let(:client) { Mongo::Client.new(uri) }
9
9
 
10
- before do
11
- if uri.nil?
12
- skip "ATLAS_URI not set in environment"
13
- end
14
- end
10
+ require_atlas
15
11
 
16
12
  describe 'ping' do
17
13
  it 'works' do