mongo 2.0.6 → 2.1.0.beta

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 (119) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/mongo.rb +2 -0
  5. data/lib/mongo/bulk_write.rb +1 -0
  6. data/lib/mongo/bulk_write/bulk_writable.rb +87 -31
  7. data/lib/mongo/bulk_write/deletable.rb +8 -7
  8. data/lib/mongo/bulk_write/insertable.rb +4 -3
  9. data/lib/mongo/bulk_write/ordered_bulk_write.rb +6 -6
  10. data/lib/mongo/bulk_write/replacable.rb +4 -3
  11. data/lib/mongo/bulk_write/result.rb +138 -0
  12. data/lib/mongo/bulk_write/unordered_bulk_write.rb +5 -8
  13. data/lib/mongo/bulk_write/updatable.rb +8 -7
  14. data/lib/mongo/client.rb +36 -4
  15. data/lib/mongo/cluster.rb +39 -4
  16. data/lib/mongo/cluster/topology/replica_set.rb +20 -4
  17. data/lib/mongo/cluster/topology/sharded.rb +1 -1
  18. data/lib/mongo/collection.rb +282 -29
  19. data/lib/mongo/collection/view/aggregation.rb +32 -4
  20. data/lib/mongo/collection/view/iterable.rb +2 -1
  21. data/lib/mongo/collection/view/map_reduce.rb +3 -1
  22. data/lib/mongo/collection/view/readable.rb +89 -14
  23. data/lib/mongo/collection/view/writable.rb +11 -5
  24. data/lib/mongo/cursor.rb +11 -3
  25. data/lib/mongo/dbref.rb +113 -0
  26. data/lib/mongo/error.rb +6 -2
  27. data/lib/mongo/error/parser.rb +1 -1
  28. data/lib/mongo/event/description_changed.rb +1 -1
  29. data/lib/mongo/grid/file.rb +1 -1
  30. data/lib/mongo/grid/fs.rb +2 -5
  31. data/lib/mongo/monitoring.rb +199 -0
  32. data/lib/mongo/monitoring/command_log_subscriber.rb +88 -0
  33. data/lib/mongo/monitoring/event.rb +17 -0
  34. data/lib/mongo/monitoring/event/command_failed.rb +96 -0
  35. data/lib/mongo/monitoring/event/command_started.rb +88 -0
  36. data/lib/mongo/monitoring/event/command_succeeded.rb +96 -0
  37. data/lib/mongo/monitoring/publishable.rb +96 -0
  38. data/lib/mongo/operation.rb +1 -0
  39. data/lib/mongo/operation/executable.rb +1 -1
  40. data/lib/mongo/operation/parallel_scan.rb +76 -0
  41. data/lib/mongo/operation/parallel_scan/result.rb +72 -0
  42. data/lib/mongo/operation/specifiable.rb +18 -0
  43. data/lib/mongo/operation/write/bulk/bulk_delete.rb +1 -1
  44. data/lib/mongo/operation/write/bulk/bulk_insert.rb +1 -1
  45. data/lib/mongo/operation/write/bulk/bulk_mergable.rb +2 -2
  46. data/lib/mongo/operation/write/bulk/bulk_update.rb +1 -1
  47. data/lib/mongo/operation/write/bulk/bulk_update/result.rb +13 -1
  48. data/lib/mongo/protocol/delete.rb +8 -13
  49. data/lib/mongo/protocol/get_more.rb +13 -13
  50. data/lib/mongo/protocol/insert.rb +8 -13
  51. data/lib/mongo/protocol/kill_cursors.rb +7 -11
  52. data/lib/mongo/protocol/query.rb +58 -20
  53. data/lib/mongo/protocol/reply.rb +12 -0
  54. data/lib/mongo/protocol/update.rb +13 -14
  55. data/lib/mongo/server.rb +23 -2
  56. data/lib/mongo/server/connectable.rb +0 -22
  57. data/lib/mongo/server/connection.rb +29 -0
  58. data/lib/mongo/server/description.rb +23 -1
  59. data/lib/mongo/server/monitor.rb +17 -1
  60. data/lib/mongo/server/monitor/connection.rb +24 -0
  61. data/lib/mongo/socket/ssl.rb +28 -16
  62. data/lib/mongo/socket/tcp.rb +1 -1
  63. data/lib/mongo/socket/unix.rb +1 -1
  64. data/lib/mongo/uri.rb +12 -5
  65. data/lib/mongo/version.rb +1 -1
  66. data/spec/mongo/auth/cr_spec.rb +9 -1
  67. data/spec/mongo/auth/ldap_spec.rb +9 -1
  68. data/spec/mongo/auth/scram_spec.rb +9 -1
  69. data/spec/mongo/auth/x509_spec.rb +9 -1
  70. data/spec/mongo/{bulk/bulk_write_spec.rb → bulk_write_spec.rb} +15 -15
  71. data/spec/mongo/client_spec.rb +42 -0
  72. data/spec/mongo/cluster/topology/replica_set_spec.rb +16 -9
  73. data/spec/mongo/cluster/topology/sharded_spec.rb +11 -3
  74. data/spec/mongo/cluster/topology/single_spec.rb +12 -4
  75. data/spec/mongo/cluster_spec.rb +55 -10
  76. data/spec/mongo/collection/view/aggregation_spec.rb +123 -1
  77. data/spec/mongo/collection/view/explainable_spec.rb +1 -1
  78. data/spec/mongo/collection/view/map_reduce_spec.rb +1 -1
  79. data/spec/mongo/collection/view/readable_spec.rb +251 -6
  80. data/spec/mongo/collection/view/writable_spec.rb +4 -4
  81. data/spec/mongo/collection/view_spec.rb +233 -71
  82. data/spec/mongo/collection_spec.rb +905 -9
  83. data/spec/mongo/crud_spec.rb +2 -2
  84. data/spec/mongo/cursor_spec.rb +3 -3
  85. data/spec/mongo/dbref_spec.rb +149 -0
  86. data/spec/mongo/monitoring_spec.rb +168 -0
  87. data/spec/mongo/operation/map_reduce_spec.rb +1 -1
  88. data/spec/mongo/operation/write/bulk/bulk_delete_spec.rb +1 -1
  89. data/spec/mongo/operation/write/bulk/bulk_insert_spec.rb +2 -2
  90. data/spec/mongo/operation/write/bulk/bulk_update_spec.rb +1 -1
  91. data/spec/mongo/operation/write/delete_spec.rb +1 -1
  92. data/spec/mongo/operation/write/insert_spec.rb +2 -2
  93. data/spec/mongo/operation/write/update_spec.rb +1 -1
  94. data/spec/mongo/protocol/query_spec.rb +0 -29
  95. data/spec/mongo/server/connection_pool_spec.rb +18 -6
  96. data/spec/mongo/server/connection_spec.rb +12 -4
  97. data/spec/mongo/server/description_spec.rb +7 -3
  98. data/spec/mongo/server/monitor_spec.rb +30 -0
  99. data/spec/mongo/server_discovery_and_monitoring_spec.rb +11 -4
  100. data/spec/mongo/server_selection_spec.rb +14 -6
  101. data/spec/mongo/server_spec.rb +27 -8
  102. data/spec/mongo/socket/ssl_spec.rb +94 -8
  103. data/spec/mongo/uri_spec.rb +25 -9
  104. data/spec/spec_helper.rb +29 -20
  105. data/spec/support/authorization.rb +19 -4
  106. data/spec/support/certificates/client.pem +4 -4
  107. data/spec/support/crud/read.rb +9 -10
  108. data/spec/support/crud/write.rb +24 -20
  109. data/spec/support/sdam/rs/equal_electionids.yml +45 -0
  110. data/spec/support/sdam/rs/new_primary_new_electionid.yml +98 -0
  111. data/spec/support/sdam/rs/null_election_id.yml +144 -0
  112. data/spec/support/sdam/rs/primary_disconnect_electionid.yml +124 -0
  113. data/spec/support/sdam/sharded/mongos_disconnect.yml +104 -0
  114. data/spec/support/server_discovery_and_monitoring.rb +19 -2
  115. data/spec/support/shared/bulk_write.rb +26 -22
  116. data/spec/support/shared/server_selector.rb +2 -1
  117. metadata +31 -7
  118. metadata.gz.sig +0 -0
  119. data/lib/mongo/error/invalid_uri_option.rb +0 -38
@@ -37,6 +37,15 @@ module Mongo
37
37
  # Delegate necessary operations to the collection.
38
38
  def_delegators :collection, :database
39
39
 
40
+ # Options mapping for an aggregation.
41
+ #
42
+ # @since 2.1.0
43
+ OPTIONS_MAP = {
44
+ :allow_disk_use => :allowDiskUse,
45
+ :max_time_ms => :maxTimeMS,
46
+ :explain => :explain
47
+ }
48
+
40
49
  # Set to true if disk usage is allowed during the aggregation.
41
50
  #
42
51
  # @example Set disk usage flag.
@@ -49,7 +58,7 @@ module Mongo
49
58
  #
50
59
  # @since 2.0.0
51
60
  def allow_disk_use(value = nil)
52
- configure(:allowDiskUse, value)
61
+ configure(__method__, value)
53
62
  end
54
63
 
55
64
  # Initialize the aggregation for the provided collection view, pipeline
@@ -89,11 +98,28 @@ module Mongo
89
98
  :selector => {
90
99
  :aggregate => collection.name,
91
100
  :pipeline => pipeline,
92
- :cursor => view.batch_size ? { :batchSize => view.batch_size } : {}
93
- }.merge!(options)
101
+ :cursor => cursor,
102
+ }.merge!(agg_options)
94
103
  }
95
104
  end
96
105
 
106
+ def agg_options
107
+ @agg_options ||= options.each.reduce({}) do |opts, (key, value)|
108
+ OPTIONS_MAP[key] ? opts.merge!(OPTIONS_MAP[key] => value) : opts
109
+ end
110
+ end
111
+
112
+ def cursor
113
+ if options[:use_cursor] == true || options[:use_cursor].nil?
114
+ batch_size_doc
115
+ end
116
+ end
117
+
118
+ def batch_size_doc
119
+ (value = options[:batch_size] || view.batch_size) ?
120
+ { :batchSize => value } : {}
121
+ end
122
+
97
123
  def explain_options
98
124
  { :explain => true }
99
125
  end
@@ -110,7 +136,9 @@ module Mongo
110
136
  begin
111
137
  initial_query_op.execute(server.context)
112
138
  rescue Mongo::Error::NeedPrimaryServer
113
- warn 'Rerouting the Aggregation operation to the primary server.'
139
+ log_warn([
140
+ 'Rerouting the Aggregation operation to the primary server.'
141
+ ])
114
142
  server = ServerSelector.get(mode: :primary).select_server(cluster)
115
143
  initial_query_op.execute(server.context)
116
144
  end
@@ -36,7 +36,8 @@ module Mongo
36
36
  # @yieldparam [ Hash ] Each matching document.
37
37
  def each
38
38
  server = read.select_server(cluster)
39
- cursor = Cursor.new(view, send_initial_query(server), server).to_enum
39
+ initial_query = send_initial_query(server)
40
+ cursor = Cursor.new(view, initial_query, server).to_enum
40
41
  cursor.each do |doc|
41
42
  yield doc
42
43
  end if block_given?
@@ -177,7 +177,9 @@ module Mongo
177
177
  begin
178
178
  initial_query_op.execute(server.context)
179
179
  rescue Mongo::Error::NeedPrimaryServer
180
- warn 'Rerouting the MapReduce operation to the primary server.'
180
+ log_warn([
181
+ 'Rerouting the MapReduce operation to the primary server.'
182
+ ])
181
183
  server = ServerSelector.get(mode: :primary).select_server(cluster)
182
184
  initial_query_op.execute(server.context)
183
185
  end
@@ -32,10 +32,22 @@ module Mongo
32
32
  :$comment => :comment,
33
33
  :$snapshot => :snapshot,
34
34
  :$maxScan => :max_scan,
35
+ :$maxTimeMS => :max_time_ms,
35
36
  :$showDiskLoc => :show_disk_loc,
36
37
  :$explain => :explained?
37
38
  }.freeze
38
39
 
40
+ # Options to cursor flags mapping.
41
+ #
42
+ # @since 2.1.0
43
+ CURSOR_FLAGS_MAP = {
44
+ :allow_partial_results => [ :partial ],
45
+ :oplog_replay => [ :oplog_replay ],
46
+ :no_cursor_timeout => [ :no_cursor_timeout ],
47
+ :tailable => [ :tailable_cursor ],
48
+ :tailable_await => [ :await_data, :tailable_cursor]
49
+ }.freeze
50
+
39
51
  # Execute an aggregation on the collection view.
40
52
  #
41
53
  # @example Aggregate documents.
@@ -53,6 +65,35 @@ module Mongo
53
65
  Aggregation.new(self, pipeline, options)
54
66
  end
55
67
 
68
+ # Execute a parallel scan on the collection view.
69
+ # Returns a list of up to cursor_count cursors that can be iterated concurrently.
70
+ # As long as the collection is not modified during scanning, each document appears once
71
+ # in one of the cursors' result sets.
72
+ #
73
+ # @example Execute a parallel collection scan.
74
+ # view.parallel_scan(2)
75
+ #
76
+ # @param [ Integer ] cursor_count The max number of cursors to return.
77
+ #
78
+ # @return [ Array<Cursor> ] An array of cursors.
79
+ #
80
+ # @since 2.1
81
+ def parallel_scan(cursor_count)
82
+ server = read.select_server(cluster)
83
+ Operation::ParallelScan.new(
84
+ :coll_name => collection.name,
85
+ :db_name => database.name,
86
+ :cursor_count => cursor_count
87
+ ).execute(server.context).cursor_ids.map do |cursor_id|
88
+ result = Operation::Read::GetMore.new({ :to_return => 0,
89
+ :cursor_id => cursor_id,
90
+ :db_name => database.name,
91
+ :coll_name => collection.name
92
+ }).execute(server.context)
93
+ Cursor.new(self, result, server)
94
+ end
95
+ end
96
+
56
97
  # Allows the query to get partial results if some shards are down.
57
98
  #
58
99
  # @example Allow partial results.
@@ -111,6 +152,8 @@ module Mongo
111
152
  # @option options :hint [ Hash ] Override default index selection and force
112
153
  # MongoDB to use a specific index for the query.
113
154
  # @option options :limit [ Integer ] Max number of docs to return.
155
+ # @option options :max_time_ms [ Integer ] The maximum amount of time to allow the
156
+ # command to run.
114
157
  # @option options :read [ Hash ] The read preference for this command.
115
158
  #
116
159
  # @return [ Integer ] The document count.
@@ -121,6 +164,7 @@ module Mongo
121
164
  cmd[:skip] = options[:skip] if options[:skip]
122
165
  cmd[:hint] = options[:hint] if options[:hint]
123
166
  cmd[:limit] = options[:limit] if options[:limit]
167
+ cmd[:maxTimeMS] = options[:max_time_ms] if options[:max_time_ms]
124
168
  database.command(cmd, options).n
125
169
  end
126
170
 
@@ -132,18 +176,19 @@ module Mongo
132
176
  # @param [ String, Symbol ] field_name The name of the field.
133
177
  # @param [ Hash ] options Options for the distinct command.
134
178
  #
179
+ # @option options :max_time_ms [ Integer ] The maximum amount of time to allow the
180
+ # command to run.
135
181
  # @option options :read [ Hash ] The read preference for this command.
136
182
  #
137
183
  # @return [ Array<Object> ] The list of distinct values.
138
184
  #
139
185
  # @since 2.0.0
140
186
  def distinct(field_name, options={})
141
- database.command({
142
- :distinct => collection.name,
143
- :key => field_name.to_s,
144
- :query => selector },
145
- options
146
- ).documents.first['values']
187
+ cmd = { :distinct => collection.name,
188
+ :key => field_name.to_s,
189
+ :query => selector }
190
+ cmd[:maxTimeMS] = options[:max_time_ms] if options[:max_time_ms]
191
+ database.command(cmd, options).first['values']
147
192
  end
148
193
 
149
194
  # The index that MongoDB will be forced to use for the query.
@@ -249,7 +294,7 @@ module Mongo
249
294
  # @since 2.0.0
250
295
  def read(value = nil)
251
296
  return default_read if value.nil?
252
- configure(:read, value)
297
+ configure(:read, value.is_a?(Hash) ? ServerSelector.get(value) : value)
253
298
  end
254
299
 
255
300
  # Set whether the disk location should be shown for each document.
@@ -312,6 +357,34 @@ module Mongo
312
357
  configure(:sort, spec)
313
358
  end
314
359
 
360
+ # “meta” operators that let you modify the output or behavior of a query.
361
+ #
362
+ # @example Set the modifiers document.
363
+ # view.modifiers(:$orderby => Mongo::Index::ASCENDING)
364
+ #
365
+ # @param [ Hash ] doc The modifiers document.
366
+ #
367
+ # @return [ Hash, View ] Either the modifiers document or a new +View+.
368
+ #
369
+ # @since 2.1.0
370
+ def modifiers(doc = nil)
371
+ configure(:modifiers, doc)
372
+ end
373
+
374
+ # A cumulative time limit in milliseconds for processing operations on a cursor.
375
+ #
376
+ # @example Set the max time ms value.
377
+ # view.max_time_ms(500)
378
+ #
379
+ # @param [ Integer ] max The max time in milliseconds.
380
+ #
381
+ # @return [ Integer, View ] Either the max time ms value or a new +View+.
382
+ #
383
+ # @since 2.1.0
384
+ def max_time_ms(max = nil)
385
+ configure(:max_time_ms, max)
386
+ end
387
+
315
388
  private
316
389
 
317
390
  def default_read(read = nil)
@@ -319,15 +392,17 @@ module Mongo
319
392
  end
320
393
 
321
394
  def flags
322
- @flags ||= (!primary? ? [ :slave_ok ] : [])
395
+ @flags ||= CURSOR_FLAGS_MAP.each.reduce([]) do |flags, (key, value)|
396
+ if options[key] || (options[:cursor_type] && options[:cursor_type] == key)
397
+ flags.push(*value)
398
+ end
399
+ flags
400
+ end
323
401
  end
324
402
 
325
403
  def has_special_fields?
326
- sort || hint || comment || max_scan || show_disk_loc || snapshot || explained? || cluster.sharded?
327
- end
328
-
329
- def primary?
330
- read.name == :primary
404
+ modifiers || sort || hint || comment || max_time_ms || max_scan ||
405
+ show_disk_loc || snapshot || explained? || cluster.sharded?
331
406
  end
332
407
 
333
408
  def query_options
@@ -349,7 +424,7 @@ module Mongo
349
424
 
350
425
  def special_selector
351
426
  SPECIAL_FIELDS.reduce({}) do |hash, (key, method)|
352
- value = send(method)
427
+ value = send(method) || (options[:modifiers] && options[:modifiers][key])
353
428
  hash[key] = value if value
354
429
  hash
355
430
  end
@@ -34,10 +34,11 @@ module Mongo
34
34
  cmd = { :findandmodify => collection.name, :query => selector, :remove => true }
35
35
  cmd[:fields] = projection if projection
36
36
  cmd[:sort] = sort if sort
37
+ cmd[:maxTimeMS] = max_time_ms if max_time_ms
37
38
  database.command(cmd).first['value']
38
39
  end
39
40
 
40
- # Finds a single document and replace it.
41
+ # Finds a single document and replaces it.
41
42
  #
42
43
  # @example Find a document and replace it, returning the original.
43
44
  # view.find_one_and_replace({ name: 'test' }, :return_document => :before)
@@ -45,7 +46,7 @@ module Mongo
45
46
  # @example Find a document and replace it, returning the new document.
46
47
  # view.find_one_and_replace({ name: 'test' }, :return_document => :after)
47
48
  #
48
- # @param [ BSON::Document ] replacement The updates.
49
+ # @param [ BSON::Document ] replacement The replacement.
49
50
  # @param [ Hash ] opts The options.
50
51
  #
51
52
  # @option opts [ Symbol ] :return_document Either :before or :after.
@@ -79,6 +80,7 @@ module Mongo
79
80
  cmd[:sort] = sort if sort
80
81
  cmd[:new] = !!(opts[:return_document] && opts[:return_document] == :after)
81
82
  cmd[:upsert] = opts[:upsert] if opts[:upsert]
83
+ cmd[:maxTimeMS] = max_time_ms if max_time_ms
82
84
  value = database.command(cmd).first['value']
83
85
  value unless value.nil? || value.empty?
84
86
  end
@@ -112,7 +114,7 @@ module Mongo
112
114
  # @example Replace a single document.
113
115
  # collection_view.replace_one({ name: 'test' })
114
116
  #
115
- # @param [ Hash ] document The document to replace.
117
+ # @param [ Hash ] replacement The replacement document.
116
118
  # @param [ Hash ] opts The options.
117
119
  #
118
120
  # @option opts [ true, false ] :upsert Whether to upsert if the
@@ -121,14 +123,16 @@ module Mongo
121
123
  # @return [ Result ] The response from the database.
122
124
  #
123
125
  # @since 2.0.0
124
- def replace_one(document, opts = {})
125
- update(document, false, opts)
126
+ def replace_one(replacement, opts = {})
127
+ update(replacement, false, opts)
126
128
  end
127
129
 
128
130
  # Update documents in the collection.
129
131
  #
130
132
  # @example Update multiple documents in the collection.
131
133
  # collection_view.update_many('$set' => { name: 'test' })
134
+ #
135
+ # @param [ Hash ] spec The update statement.
132
136
  # @param [ Hash ] opts The options.
133
137
  #
134
138
  # @option opts [ true, false ] :upsert Whether to upsert if the
@@ -145,6 +149,8 @@ module Mongo
145
149
  #
146
150
  # @example Update a single document in the collection.
147
151
  # collection_view.update_one('$set' => { name: 'test' })
152
+ #
153
+ # @param [ Hash ] spec The update statement.
148
154
  # @param [ Hash ] opts The options.
149
155
  #
150
156
  # @option opts [ true, false ] :upsert Whether to upsert if the
@@ -97,12 +97,16 @@ module Mongo
97
97
  end
98
98
 
99
99
  def get_more_operation
100
- Operation::Read::GetMore.new({
100
+ Operation::Read::GetMore.new(get_more_spec)
101
+ end
102
+
103
+ def get_more_spec
104
+ {
101
105
  :to_return => to_return,
102
106
  :cursor_id => @cursor_id,
103
107
  :db_name => database.name,
104
108
  :coll_name => @coll_name || collection.name
105
- })
109
+ }
106
110
  end
107
111
 
108
112
  def kill_cursors
@@ -110,7 +114,11 @@ module Mongo
110
114
  end
111
115
 
112
116
  def kill_cursors_operation
113
- Operation::KillCursors.new({ :cursor_ids => [ @cursor_id ]})
117
+ Operation::KillCursors.new(kill_cursors_spec)
118
+ end
119
+
120
+ def kill_cursors_spec
121
+ { :cursor_ids => [ @cursor_id ]}
114
122
  end
115
123
 
116
124
  def limited?
@@ -0,0 +1,113 @@
1
+ # Copyright (C) 2015 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the 'License');
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an 'AS IS' BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+
17
+ # Represents a DBRef document in the database.
18
+ #
19
+ # @since 2.1.0
20
+ class DBRef
21
+ include BSON::JSON
22
+
23
+ # The constant for the collection reference field.
24
+ #
25
+ # @since 2.1.0
26
+ COLLECTION = '$ref'.freeze
27
+
28
+ # The constant for the id field.
29
+ #
30
+ # @since 2.1.0
31
+ ID = '$id'.freeze
32
+
33
+ # The constant for the database field.
34
+ #
35
+ # @since 2.1.0
36
+ DATABASE = '$db'.freeze
37
+
38
+ # @return [ String ] collection The collection name.
39
+ attr_reader :collection
40
+
41
+ # @return [ BSON::ObjectId ] id The referenced document id.
42
+ attr_reader :id
43
+
44
+ # @return [ String ] database The database name.
45
+ attr_reader :database
46
+
47
+ # Get the DBRef as a JSON document
48
+ #
49
+ # @example Get the DBRef as a JSON hash.
50
+ # dbref.as_json
51
+ #
52
+ # @return [ Hash ] The max key as a JSON hash.
53
+ #
54
+ # @since 2.1.0
55
+ def as_json(*args)
56
+ document = { '$ref' => collection, '$id' => id }
57
+ document.merge!('$db' => database) if database
58
+ document
59
+ end
60
+
61
+ # Instantiate a new DBRef.
62
+ #
63
+ # @example Create the DBRef.
64
+ # Mongo::DBRef.new('users', id, 'database')
65
+ #
66
+ # @param [ String ] collection The collection name.
67
+ # @param [ BSON::ObjectId ] id The object id.
68
+ # @param [ String ] database The database name.
69
+ #
70
+ # @since 2.1.0
71
+ def initialize(collection, id, database = nil)
72
+ @collection = collection
73
+ @id = id
74
+ @database = database
75
+ end
76
+
77
+ # Converts the DBRef to raw BSON.
78
+ #
79
+ # @example Convert the DBRef to raw BSON.
80
+ # dbref.to_bson
81
+ #
82
+ # @param [ String ] encoded The encoded BSON to append to.
83
+ #
84
+ # @return [ String ] The raw BSON.
85
+ #
86
+ # @since 2.1.0
87
+ def to_bson(encoded = ''.force_encoding(BSON::BINARY))
88
+ as_json.to_bson(encoded)
89
+ end
90
+
91
+ module ClassMethods
92
+
93
+ # Deserialize the hash from BSON, converting to a DBRef if appropriate.
94
+ #
95
+ # @param [ IO ] bson The bson representing a hash.
96
+ #
97
+ # @return [ Hash, DBRef ] The decoded hash or DBRef.
98
+ #
99
+ # @see http://bsonspec.org/#/specification
100
+ #
101
+ # @since 2.0.0
102
+ def from_bson(bson)
103
+ decoded = super
104
+ if ref = decoded['$ref']
105
+ decoded = DBRef.new(ref, decoded['$id'], decoded['$db'])
106
+ end
107
+ decoded
108
+ end
109
+ end
110
+ end
111
+
112
+ ::Hash.send(:extend, DBRef::ClassMethods)
113
+ end