Class: Mongo::Database

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Retryable
Defined in:
lib/mongo/database.rb,
lib/mongo/database/view.rb,
lib/mongo/database/cursor_command_view.rb

Overview

Represents a database on the db server and operations that can execute on it at this level.

Since:

  • 2.0.0

Defined Under Namespace

Classes: CursorCommandView, View

Constant Summary collapse

ADMIN =

The admin database name.

Since:

  • 2.0.0

'admin'
COMMAND =

The "collection" that database commands operate against.

Since:

  • 2.0.0

'$cmd'
DEFAULT_OPTIONS =

The default database options.

Since:

  • 2.0.0

Options::Redacted.new(database: ADMIN).freeze
NAME =
Deprecated.

Database name field constant.

Since:

  • 2.1.0

'name'
DATABASES =

Databases constant.

Since:

  • 2.1.0

'databases'
NAMESPACES =

The name of the collection that holds all the collection names.

Since:

  • 2.0.0

'system.namespaces'

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Retryable

#read_worker, #select_server, #with_overload_retry, #write_worker

Constructor Details

#initialize(client, name, options = {}) ⇒ Database

Instantiate a new database object.

Examples:

Instantiate the database.

Mongo::Database.new(client, :test)

Parameters:

  • client (Mongo::Client)

    The driver client.

  • name (String, Symbol)

    The name of the database.

  • options (Hash) (defaults to: {})

    The options.

Options Hash (options):

  • :timeout_ms (Integer)

    The operation timeout in milliseconds. Must be a non-negative integer. An explicit value of 0 means infinite. The default value is unset which means the value is inherited from the client.

Raises:

  • (Mongo::Database::InvalidName)

    If the name is nil.

Since:

  • 2.0.0



479
480
481
482
483
484
485
486
487
488
# File 'lib/mongo/database.rb', line 479

def initialize(client, name, options = {})
  raise Error::InvalidDatabaseName.new unless name
  if Lint.enabled? && !(name.is_a?(String) || name.is_a?(Symbol))
    raise "Database name must be a string or a symbol: #{name}"
  end

  @client = client
  @name = name.to_s.freeze
  @options = options.freeze
end

Instance Attribute Details

#clientClient (readonly)

Returns client The database client.

Returns:

  • (Client)

    client The database client.

Since:

  • 2.0.0



61
62
63
# File 'lib/mongo/database.rb', line 61

def client
  @client
end

#nameString (readonly)

Returns name The name of the database.

Returns:

  • (String)

    name The name of the database.

Since:

  • 2.0.0



64
65
66
# File 'lib/mongo/database.rb', line 64

def name
  @name
end

#optionsHash (readonly)

Returns options The options.

Returns:

  • (Hash)

    options The options.

Since:

  • 2.0.0



67
68
69
# File 'lib/mongo/database.rb', line 67

def options
  @options
end

Instance Method Details

#==(other) ⇒ true, false

Check equality of the database object against another. Will simply check if the names are the same.

Examples:

Check database equality.

database == other

Parameters:

  • other (Object)

    The object to check against.

Returns:

  • (true, false)

    If the objects are equal.

Since:

  • 2.0.0



94
95
96
97
98
# File 'lib/mongo/database.rb', line 94

def ==(other)
  return false unless other.is_a?(Database)

  name == other.name
end

#[](collection_name, options = {}) ⇒ Mongo::Collection Also known as: collection

Get a collection in this database by the provided name.

Examples:

Get a collection.

database[:users]

Parameters:

  • collection_name (String, Symbol)

    The name of the collection.

  • options (Hash) (defaults to: {})

    The options to the collection.

Returns:

Since:

  • 2.0.0



111
112
113
114
115
116
117
118
# File 'lib/mongo/database.rb', line 111

def [](collection_name, options = {})
  if options[:server_api]
    raise ArgumentError,
          'The :server_api option cannot be specified for collection objects. It can only be specified on Client level'
  end

  Collection.new(self, collection_name, options)
end

#aggregate(pipeline, options = {}) ⇒ Collection::View::Aggregation

Perform an aggregation on the database.

Examples:

Perform an aggregation.

collection.aggregate([ { "$listLocalSessions" => {} } ])

Parameters:

  • pipeline (Array<Hash>)

    The aggregation pipeline.

  • options (Hash) (defaults to: {})

    The aggregation options.

Options Hash (options):

  • :allow_disk_use (true, false)

    Set to true if disk usage is allowed during the aggregation.

  • :batch_size (Integer)

    The number of documents to return per batch.

  • :bypass_document_validation (true, false)

    Whether or not to skip document level validation.

  • :collation (Hash)

    The collation to use.

  • :comment (Object)

    A user-provided comment to attach to this command.

  • :max_time_ms (Integer)

    The maximum amount of time to allow the query to run, in milliseconds. This option is deprecated, use :timeout_ms instead.

  • :timeout_ms (Integer)

    The operation timeout in milliseconds. Must be a non-negative integer. An explicit value of 0 means infinite. The default value is unset which means the value is inherited from the database or the client.

  • :hint (String)

    The index to use for the aggregation.

  • :session (Session)

    The session to use.

Returns:

Since:

  • 2.10.0



568
569
570
# File 'lib/mongo/database.rb', line 568

def aggregate(pipeline, options = {})
  View.new(self, options).aggregate(pipeline, options)
end

#clusterMongo::Server

Returns Get the primary server from the cluster.

Returns:

Since:

  • 2.0.0



80
81
# File 'lib/mongo/database.rb', line 80

def_delegators :cluster,
:next_primary

#collection_names(options = {}) ⇒ Array<String>

Note:

The set of returned collection names depends on the version of MongoDB server that fulfills the request.

Get all the names of the non-system collections in the database.

See https://mongodb.com/docs/manual/reference/command/listCollections/
for more information and usage.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :filter (Hash)

    A filter on the collections returned.

  • :authorized_collections (true, false)

    A flag, when set to true and used with nameOnly: true, that allows a user without the required privilege to run the command when access control is enforced

  • :comment (Object)

    A user-provided comment to attach to this command.

  • :timeout_ms (Integer)

    The operation timeout in milliseconds. Must be a non-negative integer. An explicit value of 0 means infinite. The default value is unset which means the value is inherited from the database or the client.

Returns:

  • (Array<String>)

    Names of the collections.

Since:

  • 2.0.0



145
146
147
# File 'lib/mongo/database.rb', line 145

def collection_names(options = {})
  View.new(self, options).collection_names(options)
end

#collections(options = {}) ⇒ Array<Mongo::Collection>

Note:

The set of returned collections depends on the version of MongoDB server that fulfills the request.

Get all the non-system collections that belong to this database.

See https://mongodb.com/docs/manual/reference/command/listCollections/
for more information and usage.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :filter (Hash)

    A filter on the collections returned.

  • :authorized_collections (true, false)

    A flag, when set to true and used with name_only: true, that allows a user without the required privilege to run the command when access control is enforced.

  • :comment (Object)

    A user-provided comment to attach to this command.

  • :timeout_ms (Integer)

    The operation timeout in milliseconds. Must be a non-negative integer. An explicit value of 0 means infinite. The default value is unset which means the value is inherited from the database or the client.

Returns:

Since:

  • 2.0.0



206
207
208
# File 'lib/mongo/database.rb', line 206

def collections(options = {})
  collection_names(options).map { |name| collection(name) }
end

#command(operation, opts = {}) ⇒ Mongo::Operation::Result

Execute a command on the database.

Examples:

Execute a command.

database.command(:hello => 1)

Parameters:

  • operation (Hash)

    The command to execute.

  • opts (Hash) (defaults to: {})

    The command options.

  • options (Hash)

    a customizable set of options

Options Hash (opts):

  • :read (Hash)

    The read preference for this command.

  • :session (Session)

    The session to use for this command.

  • :execution_options (Hash)

    Options to pass to the code that executes this command. This is an internal option and is subject to change.

    • :deserialize_as_bson [ Boolean ] Whether to deserialize the response to this command using BSON types instead of native Ruby types wherever possible.

Returns:

Since:

  • 2.0.0



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/mongo/database.rb', line 232

def command(operation, opts = {})
  opts = opts.dup
  execution_opts = opts.delete(:execution_options) || {}

  txn_read_pref = (opts[:session].txn_read_preference if opts[:session] && opts[:session].in_transaction?)
  txn_read_pref ||= opts[:read] || ServerSelector::PRIMARY
  Lint.validate_underscore_read_preference(txn_read_pref)
  selector = ServerSelector.get(txn_read_pref)

  client.with_session(opts) do |session|
    context = Operation::Context.new(
      client: client,
      session: session,
      operation_timeouts: operation_timeouts(opts)
    )
    op = Operation::Command.new(
      selector: operation,
      db_name: name,
      read: selector,
      session: session
    )

    retry_enabled = client.options[:retry_reads] != false &&
                    client.options[:retry_writes] != false
    with_overload_retry(context: context, retry_enabled: retry_enabled) do
      server = selector.select_server(cluster, nil, session)
      op.execute(server, context: context, options: execution_opts)
    end
  end
end

#cursor_command(command, options = {}) ⇒ Mongo::Cursor

Run a command that returns a cursor and parse the response as a cursor.

The command is sent to the server unmodified; the driver MUST NOT inspect or alter it. If the response does not contain a cursor field an error is raised. The command is never retried.

Note: if a maxTimeMS field is already set on the command document it is left as-is. The max_time_ms option below applies only to getMore commands. Setting both timeout_ms and max_time_ms is not supported and has undefined behavior.

Examples:

Run a cursor-returning command.

database.cursor_command(checkMetadataConsistency: 1)

Parameters:

  • command (Hash)

    The command to execute.

  • options (Hash) (defaults to: {})

    The command options.

Options Hash (options):

  • :read (Hash)

    The read preference for this command, used for server selection and reused for subsequent getMores.

  • :session (Session)

    The session to use. If none is given an implicit session is created and reused for the cursor's lifetime.

  • :timeout_ms (Integer)

    The operation timeout in milliseconds.

  • :batch_size (Integer)

    The batchSize to send on getMore commands.

  • :max_time_ms (Integer)

    The maxTimeMS to send on getMore commands.

  • :comment (Object)

    A comment to attach to getMore commands.

  • :cursor_type (Symbol)

    The cursor type, :tailable or :tailable_await. Must match the flags set on the command document.

  • :timeout_mode (Symbol)

    :cursor_lifetime or :iteration.

Returns:

Raises:

Since:

  • 2.0.0



301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
# File 'lib/mongo/database.rb', line 301

def cursor_command(command, options = {})
  options = options.dup
  execution_opts = options.delete(:execution_options) || {}
  view_options = extract_cursor_command_view_options(options)

  txn_read_pref = (options[:session].txn_read_preference if options[:session] && options[:session].in_transaction?)
  txn_read_pref ||= options[:read] || ServerSelector::PRIMARY
  Lint.validate_underscore_read_preference(txn_read_pref)
  selector = ServerSelector.get(txn_read_pref)

  # The session is intentionally not wrapped in #with_session: an implicit
  # session must outlive this method and is ended by the cursor when it is
  # exhausted or closed. Until the cursor takes ownership, the session and
  # any load-balanced connection are cleaned up here on every exit path.
  session = client.get_session(options)
  context = Operation::Context.new(
    client: client,
    session: session,
    operation_timeouts: operation_timeouts(options)
  )
  op = Operation::CursorCommand.new(
    selector: command,
    db_name: name,
    read: selector,
    session: session
  )

  # Per the client-backpressure spec, retrying a generic command on
  # overload errors requires both retryable reads and writes to be
  # enabled, same as Database#command.
  retry_enabled = client.options[:retry_reads] != false &&
                  client.options[:retry_writes] != false

  server = nil
  connection = nil
  cursor = nil
  begin
    result = with_overload_retry(context: context, retry_enabled: retry_enabled) do
      server = selector.select_server(cluster, nil, session)
      if server.load_balancer?
        # The connection is checked in by the cursor when it is drained.
        connection = check_out_cursor_command_connection(server, context)
        begin
          op.execute_with_connection(connection, context: context, options: execution_opts)
        rescue StandardError
          # Release the connection before the error propagates so that
          # a retried attempt checks out a fresh one.
          connection.connection_pool.check_in(connection) unless connection.pinned?
          connection = nil
          raise
        end
      else
        op.execute(server, context: context, options: execution_opts)
      end
    end

    unless result.cursor?
      raise Error::InvalidCursorOperation,
            'The command response did not include a cursor. ' \
            'Use Database#command for commands that do not return a cursor.'
    end

    view = CursorCommandView.new(self, view_options)
    cursor = Cursor.new(view, result, server, session: session, context: context)
  ensure
    # If the cursor was created it owns the session and connection;
    # otherwise (error or no cursor in the response) release them here.
    unless cursor
      connection.connection_pool.check_in(connection) if connection && !connection.pinned?
      session.end_session if session && session.implicit?
    end
  end
  cursor
end

#drop(options = {}) ⇒ Result

Drop the database and all its associated information.

Examples:

Drop the database.

database.drop

Parameters:

  • options (Hash) (defaults to: {})

    The options for the operation.

Options Hash (options):

  • :session (Session)

    The session to use for the operation.

  • :write_concern (Hash)

    The write concern options.

  • :timeout_ms (Integer)

    The operation timeout in milliseconds. Must be a non-negative integer. An explicit value of 0 means infinite. The default value is unset which means the value is inherited from the database or the client.

Returns:

  • (Result)

    The result of the command.

Since:

  • 2.0.0



439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
# File 'lib/mongo/database.rb', line 439

def drop(options = {})
  operation = { dropDatabase: 1 }
  client.with_session(options) do |session|
    write_concern = if options[:write_concern]
                      WriteConcern.get(options[:write_concern])
                    else
                      self.write_concern
                    end
    Operation::DropDatabase.new({
                                  selector: operation,
                                  db_name: name,
                                  write_concern: write_concern,
                                  session: session
                                }).execute(
                                  next_primary(nil, session),
                                  context: Operation::Context.new(
                                    client: client,
                                    session: session,
                                    operation_timeouts: operation_timeouts(options)
                                  )
                                )
  end
end

#fs(options = {}) ⇒ Grid::FSBucket

Get the Grid "filesystem" for this database.

Parameters:

  • options (Hash) (defaults to: {})

    The GridFS options.

Options Hash (options):

  • :bucket_name (String)

    The prefix for the files and chunks collections.

  • :chunk_size (Integer)

    Override the default chunk size.

  • :fs_name (String)

    The prefix for the files and chunks collections.

  • :read (String)

    The read preference.

  • :session (Session)

    The session to use.

  • :write (Hash)

    Deprecated. Equivalent to :write_concern option.

  • :write_concern (Hash)

    The write concern options. Can be :w => Integer|String, :fsync => Boolean, :j => Boolean.

Returns:

Since:

  • 2.0.0



522
523
524
# File 'lib/mongo/database.rb', line 522

def fs(options = {})
  Grid::FSBucket.new(self, options)
end

#inspectString

Get a pretty printed string inspection for the database.

Examples:

Inspect the database.

database.inspect

Returns:

  • (String)

    The database inspection.

Since:

  • 2.0.0



498
499
500
# File 'lib/mongo/database.rb', line 498

def inspect
  "#<Mongo::Database:0x#{object_id} name=#{name}>"
end

#list_collections(options = {}) ⇒ Array<Hash>

Note:

The set of collections returned, and the schema of the information hash per collection, depends on the MongoDB server version that fulfills the request.

Get info on all the non-system collections in the database.

See https://mongodb.com/docs/manual/reference/command/listCollections/
for more information and usage.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :filter (Hash)

    A filter on the collections returned.

  • :name_only (true, false)

    Indicates whether command should return just collection/view names and type or return both the name and other information

  • :authorized_collections (true, false)

    A flag, when set to true and used with nameOnly: true, that allows a user without the required privilege to run the command when access control is enforced.

  • :comment (Object)

    A user-provided comment to attach to this command.

  • :timeout_ms (Integer)

    The operation timeout in milliseconds. Must be a non-negative integer. An explicit value of 0 means infinite. The default value is unset which means the value is inherited from the database or the client.

Returns:

  • (Array<Hash>)

    Array of information hashes, one for each collection in the database.

Since:

  • 2.0.5



178
179
180
# File 'lib/mongo/database.rb', line 178

def list_collections(options = {})
  View.new(self, options).list_collections(options)
end

#operation_timeouts(opts) ⇒ Hash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns timeout_ms value set on the operation level (if any), and/or timeout_ms that is set on collection/database/client level (if any).

Returns:

  • (Hash)

    timeout_ms value set on the operation level (if any), and/or timeout_ms that is set on collection/database/client level (if any).

Since:

  • 2.0.0



659
660
661
662
663
664
665
666
667
668
# File 'lib/mongo/database.rb', line 659

def operation_timeouts(opts)
  # TODO: We should re-evaluate if we need two timeouts separately.
  {}.tap do |result|
    if opts[:timeout_ms].nil?
      result[:inherited_timeout_ms] = timeout_ms
    else
      result[:operation_timeout_ms] = opts.delete(:timeout_ms)
    end
  end
end

#read_command(operation, opts = {}) ⇒ Hash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Execute a read command on the database, retrying the read if necessary.

Parameters:

  • operation (Hash)

    The command to execute.

  • opts (Hash) (defaults to: {})

    The command options.

Options Hash (opts):

  • :read (Hash)

    The read preference for this command.

  • :session (Session)

    The session to use for this command.

  • :comment (Object)

    A user-provided comment to attach to this command.

  • :timeout_ms (Integer)

    The operation timeout in milliseconds. Must be a non-negative integer. An explicit value of 0 means infinite. The default value is unset which means the value is inherited from the database or the client.

  • :op_name (String | nil)

    The name of the operation for tracing purposes.

Returns:

  • (Hash)

    The result of the command execution.

Since:

  • 2.0.0



394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
# File 'lib/mongo/database.rb', line 394

def read_command(operation, opts = {})
  txn_read_pref = (opts[:session].txn_read_preference if opts[:session] && opts[:session].in_transaction?)
  txn_read_pref ||= opts[:read] || ServerSelector::PRIMARY
  Lint.validate_underscore_read_preference(txn_read_pref)
  preference = ServerSelector.get(txn_read_pref)

  client.with_session(opts) do |session|
    context = Operation::Context.new(
      client: client,
      session: session,
      operation_timeouts: operation_timeouts(opts)
    )
    operation = Operation::Command.new(
      selector: operation.dup,
      db_name: name,
      read: preference,
      session: session,
      comment: opts[:comment]
    )
    op_name = opts[:op_name] || 'command'
    tracer.trace_operation(operation, context, op_name: op_name) do
      read_with_retry(session, preference, context) do |server|
        operation.execute(server, context: context)
      end
    end
  end
end

#timeout_msInteger | nil

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns Operation timeout that is for this database or for the corresponding client.

Returns:

  • (Integer | nil)

    Operation timeout that is for this database or for the corresponding client.

Since:

  • 2.0.0



651
652
653
# File 'lib/mongo/database.rb', line 651

def timeout_ms
  options[:timeout_ms] || client.timeout_ms
end

#usersView::User

Get the user view for this database.

Examples:

Get the user view.

database.users

Returns:

  • (View::User)

    The user view.

Since:

  • 2.0.0



534
535
536
# File 'lib/mongo/database.rb', line 534

def users
  Auth::User::View.new(self)
end

#watch(pipeline = [], options = {}) ⇒ ChangeStream

Note:

A change stream only allows 'majority' read concern.

Note:

This helper method is preferable to running a raw aggregation with a $changeStream stage, for the purpose of supporting resumability.

Allows users to request that notifications are sent for all changes that occur in the client's database.

Examples:

Get change notifications for a given database..

database.watch([{ '$match' => { operationType: { '$in' => ['insert', 'replace'] } } }])

Parameters:

  • pipeline (Array<Hash>) (defaults to: [])

    Optional additional filter operators.

  • options (Hash) (defaults to: {})

    The change stream options.

Options Hash (options):

  • :full_document (String)

    Allowed values: nil, 'default', 'updateLookup', 'whenAvailable', 'required'.

    The default is to not send a value (i.e. nil), which is equivalent to 'default'. By default, the change notification for partial updates will include a delta describing the changes to the document.

    When set to 'updateLookup', the change notification for partial updates will include both a delta describing the changes to the document as well as a copy of the entire document that was changed from some time after the change occurred.

    When set to 'whenAvailable', configures the change stream to return the post-image of the modified document for replace and update change events if the post-image for this event is available.

    When set to 'required', the same behavior as 'whenAvailable' except that an error is raised if the post-image is not available.

  • :full_document_before_change (String)

    Allowed values: nil, 'whenAvailable', 'required', 'off'.

    The default is to not send a value (i.e. nil), which is equivalent to 'off'.

    When set to 'whenAvailable', configures the change stream to return the pre-image of the modified document for replace, update, and delete change events if it is available.

    When set to 'required', the same behavior as 'whenAvailable' except that an error is raised if the pre-image is not available.

  • :resume_after (BSON::Document, Hash)

    Specifies the logical starting point for the new change stream.

  • :max_await_time_ms (Integer)

    The maximum amount of time for the server to wait on new documents to satisfy a change stream query.

  • :batch_size (Integer)

    The number of documents to return per batch.

  • :collation (BSON::Document, Hash)

    The collation to use.

  • :session (Session)

    The session to use.

  • :start_at_operation_time (BSON::Timestamp)

    Only return changes that occurred after the specified timestamp. Any command run against the server will return a cluster time that can be used here.

  • :comment (Object)

    A user-provided comment to attach to this command.

  • :show_expanded_events (Boolean)

    Enables the server to send the 'expanded' list of change stream events. The list of additional events included with this flag set are: createIndexes, dropIndexes, modify, create, shardCollection, reshardCollection, refineCollectionShardKey.

Returns:

  • (ChangeStream)

    The change stream object.

Since:

  • 2.6.0



635
636
637
638
639
640
641
642
643
644
645
# File 'lib/mongo/database.rb', line 635

def watch(pipeline = [], options = {})
  view_options = options.dup
  view_options[:cursor_type] = :tailable_await if options[:max_await_time_ms]

  Mongo::Collection::View::ChangeStream.new(
    Mongo::Collection::View.new(collection("#{COMMAND}.aggregate"), {}, view_options),
    pipeline,
    Mongo::Collection::View::ChangeStream::DATABASE,
    options
  )
end