123456789_123456789_123456789_123456789_123456789_

Module: Mongo::Collection::View::Writable

Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Included In:
Defined in: lib/mongo/collection/view/writable.rb

Overview

Defines write related behavior for collection view.

Since:

  • 2.0.0

Constant Summary

Instance Method Summary

Instance Method Details

#delete_many(opts = {}) ⇒ Result

Remove documents from the collection.

Examples:

Remove multiple documents from the collection.

collection_view.delete_many

Parameters:

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

    The options.

  • options (Hash)

    a customizable set of options

Options Hash (opts):

  • :collation (Hash)

    The collation to use.

  • :session (Session)

    The session to use.

  • :hint (Hash | String)

    The index to use for this operation. May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. “id”).

  • :write_concern (Hash)

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

  • :let (Hash)

    Mapping of variables to use in the command. See the server documentation for details.

  • :comment (Object)

    A user-provided comment to attach to this command.

Returns:

  • (Result)

    The response from the database.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/writable.rb', line 257

def delete_many(opts = {})
  with_session(opts) do |session|
    write_concern = if opts[:write_concern]
                      WriteConcern.get(opts[:write_concern])
                    else
                      write_concern_with_session(session)
                    end

    QueryCache.clear_namespace(collection.namespace)

    delete_doc = {
      Operation::Q => filter,
      Operation::LIMIT => 0,
      hint: opts[:hint],
      collation: opts[:collation] || opts['collation'] || collation,
    }.compact
    context = Operation::Context.new(
      client: client,
      session: session,
      operation_timeouts: operation_timeouts(opts)
    )
    operation = Operation::Delete.new(
      deletes: [ delete_doc ],
      db_name: collection.database.name,
      coll_name: collection.name,
      write_concern: write_concern,
      bypass_document_validation: !!opts[:bypass_document_validation],
      session: session,
      let: opts[:let],
      comment: opts[:comment]
    )
    tracer.trace_operation(operation, context, op_name: 'deleteMany') do
      nro_write_with_retry(write_concern, context: context) do |connection, _txn_num, context|
        gte_4_4 = connection.server.description.server_version_gte?('4.4')
        if !gte_4_4 && opts[:hint] && write_concern && !write_concern.acknowledged?
          raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
        end

        operation.execute_with_connection(connection, context: context)
      end
    end
  end
end

#delete_one(opts = {}) ⇒ Result

Remove a document from the collection.

Examples:

Remove a single document from the collection.

collection_view.delete_one

Parameters:

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

    The options.

  • options (Hash)

    a customizable set of options

Options Hash (opts):

  • :collation (Hash)

    The collation to use.

  • :comment (Object)

    A user-provided comment to attach to this command.

  • :hint (Hash | String)

    The index to use for this operation. May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. “id”).

  • :let (Hash)

    Mapping of variables to use in the command. See the server documentation for details.

  • :session (Session)

    The session to use.

  • :write_concern (Hash)

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

Returns:

  • (Result)

    The response from the database.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/writable.rb', line 326

def delete_one(opts = {})
  with_session(opts) do |session|
    write_concern = if opts[:write_concern]
                      WriteConcern.get(opts[:write_concern])
                    else
                      write_concern_with_session(session)
                    end

    QueryCache.clear_namespace(collection.namespace)

    delete_doc = {
      Operation::Q => filter,
      Operation::LIMIT => 1,
      hint: opts[:hint],
      collation: opts[:collation] || opts['collation'] || collation,
    }.compact

    context = Operation::Context.new(
      client: client,
      session: session,
      operation_timeouts: operation_timeouts(opts)
    )
    write_with_retry(write_concern, context: context) do |connection, txn_num, context|
      gte_4_4 = connection.server.description.server_version_gte?('4.4')
      if !gte_4_4 && opts[:hint] && write_concern && !write_concern.acknowledged?
        raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
      end

      Operation::Delete.new(
        deletes: [ delete_doc ],
        db_name: collection.database.name,
        coll_name: collection.name,
        write_concern: write_concern,
        bypass_document_validation: !!opts[:bypass_document_validation],
        session: session,
        txn_num: txn_num,
        let: opts[:let],
        comment: opts[:comment]
      ).execute_with_connection(connection, context: context)
    end
  end
end

#find_one_and_delete(opts = {}) ⇒ BSON::Document?

Finds a single document in the database via findAndModify and deletes it, returning the original document.

Examples:

Find one document and delete it.

view.find_one_and_delete

Parameters:

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

    The options.

  • options (Hash)

    a customizable set of options

Options Hash (opts):

  • :max_time_ms (Integer)

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

  • :projection (Hash)

    The fields to include or exclude in the returned doc.

  • :sort (Hash)

    The key and direction pairs by which the result set will be sorted.

  • :collation (Hash)

    The collation to use.

  • :session (Session)

    The session to use.

  • :hint (Hash | String)

    The index to use for this operation. May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. “id”).

  • :write_concern (Hash)

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

  • :let (Hash)

    Mapping of variables to use in the command. See the server documentation for details.

  • :comment (Object)

    A user-provided comment to attach to this command.

Returns:

  • (BSON::Document, nil)

    The document, if found.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/writable.rb', line 61

def find_one_and_delete(opts = {})
  with_session(opts) do |session|
    write_concern = if opts[:write_concern]
                      WriteConcern.get(opts[:write_concern])
                    else
                      write_concern_with_session(session)
                    end

    QueryCache.clear_namespace(collection.namespace)

    cmd = {
      findAndModify: collection.name,
      query: filter,
      remove: true,
      fields: projection,
      sort: sort,
      maxTimeMS: max_time_ms,
      bypassDocumentValidation: opts[:bypass_document_validation],
      hint: opts[:hint],
      collation: opts[:collation] || opts['collation'] || collation,
      let: opts[:let],
      comment: opts[:comment],
    }.compact

    context = Operation::Context.new(
      client: client,
      session: session,
      operation_timeouts: operation_timeouts(opts)
    )
    write_with_retry(write_concern, context: context) do |connection, txn_num, context|
      gte_4_4 = connection.server.description.server_version_gte?('4.4')
      if !gte_4_4 && opts[:hint] && write_concern && !write_concern.acknowledged?
        raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
      end

      Operation::WriteCommand.new(
        selector: cmd,
        db_name: database.name,
        write_concern: write_concern,
        session: session,
        txn_num: txn_num
      ).execute_with_connection(connection, context: context)
    end
  end.first&.fetch('value', nil)
end

#find_one_and_replace(replacement, opts = {}) ⇒ BSON::Document

Finds a single document and replaces it.

Examples:

Find a document and replace it, returning the original.

view.find_one_and_replace({ name: 'test' }, :return_document => :before)

Find a document and replace it, returning the new document.

view.find_one_and_replace({ name: 'test' }, :return_document => :after)

Parameters:

  • replacement (BSON::Document)

    The replacement.

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

    The options.

  • options (Hash)

    a customizable set of options

Options Hash (opts):

  • :return_document (Symbol)

    Either :before or :after.

  • :upsert (true, false)

    Whether to upsert if the document doesn’t exist.

  • :bypass_document_validation (true, false)

    Whether or not to skip document level validation.

  • :collation (Hash)

    The collation to use.

  • :hint (Hash | String)

    The index to use for this operation. May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. “id”).

  • :write_concern (Hash)

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

  • :let (Hash)

    Mapping of variables to use in the command. See the server documentation for details.

Returns:

  • (BSON::Document)

    The document.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/writable.rb', line 137

def find_one_and_replace(replacement, opts = {})
  find_one_and_update(replacement, opts)
end

#find_one_and_update(document, opts = {}) ⇒ BSON::Document | nil

Finds a single document and updates it.

an update should apply.

Examples:

Find a document and update it, returning the original.

view.find_one_and_update({ "$set" => { name: 'test' }}, :return_document => :before)

Parameters:

  • document (BSON::Document)

    The updates.

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

    The options.

  • options (Hash)

    a customizable set of options

Options Hash (opts):

  • :max_time_ms (Integer)

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

  • :projection (Hash)

    The fields to include or exclude in the returned doc.

  • :sort (Hash)

    The key and direction pairs by which the result set will be sorted.

  • :return_document (Symbol)

    Either :before or :after.

  • :upsert (true, false)

    Whether to upsert if the document doesn’t exist.

  • :bypass_document_validation (true, false)

    Whether or not to skip document level validation.

  • :collation (Hash)

    The collation to use.

  • :array_filters (Array)

    A set of filters specifying to which array elements

  • :session (Session)

    The session to use.

  • :hint (Hash | String)

    The index to use for this operation. May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. “id”).

  • :write_concern (Hash)

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

  • :let (Hash)

    Mapping of variables to use in the command. See the server documentation for details.

  • :comment (Object)

    A user-provided comment to attach to this command.

Returns:

  • (BSON::Document | nil)

    The document or nil if none is found.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/writable.rb', line 179

def find_one_and_update(document, opts = {})
  value = with_session(opts) do |session|
    write_concern = if opts[:write_concern]
                      WriteConcern.get(opts[:write_concern])
                    else
                      write_concern_with_session(session)
                    end

    QueryCache.clear_namespace(collection.namespace)

    cmd = {
      findAndModify: collection.name,
      query: filter,
      arrayFilters: opts[:array_filters] || opts['array_filters'],
      update: document,
      fields: projection,
      sort: sort,
      new: !!(opts[:return_document] && opts[:return_document] == :after),
      upsert: opts[:upsert],
      maxTimeMS: max_time_ms,
      bypassDocumentValidation: opts[:bypass_document_validation],
      hint: opts[:hint],
      collation: opts[:collation] || opts['collation'] || collation,
      let: opts[:let],
      comment: opts[:comment]
    }.compact

    context = Operation::Context.new(
      client: client,
      session: session,
      operation_timeouts: operation_timeouts(opts)
    )
    operation = Operation::WriteCommand.new(
      selector: cmd,
      db_name: database.name,
      write_concern: write_concern,
      session: session
    )
    value = tracer.trace_operation(operation, context, op_name: 'findOneAndUpdate') do
      write_with_retry(write_concern, context: context) do |connection, txn_num, context|
        gte_4_4 = connection.server.description.server_version_gte?('4.4')
        if !gte_4_4 && opts[:hint] && write_concern && !write_concern.acknowledged?
          raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
        end

        operation.txn_num = txn_num
        operation.execute_with_connection(connection, context: context)
      end
    end.first&.fetch('value', nil)
    value unless value.nil? || value.empty?
  end
end

#replace_one(replacement, opts = {}) ⇒ Result

Replaces a single document in the database with the new document.

Examples:

Replace a single document.

collection_view.replace_one({ name: 'test' })

Parameters:

  • replacement (Hash)

    The replacement document.

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

    The options.

  • options (Hash)

    a customizable set of options

Options Hash (opts):

  • :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.

  • :hint (Hash | String)

    The index to use for this operation. May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. “id”).

  • :let (Hash)

    Mapping of variables to use in the command. See the server documentation for details.

  • :session (Session)

    The session to use.

  • :write_concern (Hash)

    The write concern options.

  • :upsert (true, false)

    Whether to upsert if the document doesn’t exist. Can be :w => Integer, :fsync => Boolean, :j => Boolean.

  • :sort (Hash)

    Specifies which document the operation replaces if the query matches multiple documents. The first document matched by the sort order will be replaced. This option is only supported by servers >= 8.0. Older servers will report an error for using this option.

Returns:

  • (Result)

    The response from the database.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/writable.rb', line 404

def replace_one(replacement, opts = {})
  with_session(opts) do |session|
    write_concern = if opts[:write_concern]
                      WriteConcern.get(opts[:write_concern])
                    else
                      write_concern_with_session(session)
                    end
    validate_replacement_documents!(replacement)

    QueryCache.clear_namespace(collection.namespace)

    update_doc = {
      Operation::Q => filter,
      arrayFilters: opts[:array_filters] || opts['array_filters'],
      Operation::U => replacement,
      hint: opts[:hint],
      collation: opts[:collation] || opts['collation'] || collation,
      sort: opts[:sort] || opts['sort'],
    }.compact
    update_doc['upsert'] = true if opts[:upsert]

    context = Operation::Context.new(
      client: client,
      session: session,
      operation_timeouts: operation_timeouts(opts)
    )
    write_with_retry(write_concern, context: context) do |connection, txn_num, context|
      gte_4_2 = connection.server.description.server_version_gte?('4.2')
      if !gte_4_2 && opts[:hint] && write_concern && !write_concern.acknowledged?
        raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
      end

      Operation::Update.new(
        updates: [ update_doc ],
        db_name: collection.database.name,
        coll_name: collection.name,
        write_concern: write_concern,
        bypass_document_validation: !!opts[:bypass_document_validation],
        session: session,
        txn_num: txn_num,
        let: opts[:let],
        comment: opts[:comment]
      ).execute_with_connection(connection, context: context)
    end
  end
end

#update_many(spec, opts = {}) ⇒ Result

Update documents in the collection.

Examples:

Update multiple documents in the collection.

collection_view.update_many('$set' => { name: 'test' })

Parameters:

  • spec (Hash | Array<Hash>)

    The update document or pipeline.

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

    The options.

  • options (Hash)

    a customizable set of options

Options Hash (opts):

  • :array_filters (Array)

    A set of filters specifying to which array elements an update should apply.

  • :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.

  • :hint (Hash | String)

    The index to use for this operation. May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. “id”).

  • :let (Hash)

    Mapping of variables to use in the command. See the server documentation for details.

  • :session (Session)

    The session to use.

  • :upsert (true, false)

    Whether to upsert if the document doesn’t exist.

  • :write_concern (Hash)

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

Returns:

  • (Result)

    The response from the database.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/writable.rb', line 483

def update_many(spec, opts = {})
  with_session(opts) do |session|
    write_concern = if opts[:write_concern]
                      WriteConcern.get(opts[:write_concern])
                    else
                      write_concern_with_session(session)
                    end
    validate_update_documents!(spec)

    QueryCache.clear_namespace(collection.namespace)

    update_doc = {
      Operation::Q => filter,
      arrayFilters: opts[:array_filters] || opts['array_filters'],
      Operation::U => spec,
      Operation::MULTI => true,
      hint: opts[:hint],
      collation: opts[:collation] || opts['collation'] || collation,
    }.compact
    update_doc['upsert'] = true if opts[:upsert]

    context = Operation::Context.new(
      client: client,
      session: session,
      operation_timeouts: operation_timeouts(opts)
    )
    nro_write_with_retry(write_concern, context: context) do |connection, _txn_num, context|
      gte_4_2 = connection.server.description.server_version_gte?('4.2')
      if !gte_4_2 && opts[:hint] && write_concern && !write_concern.acknowledged?
        raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
      end

      Operation::Update.new(
        updates: [ update_doc ],
        db_name: collection.database.name,
        coll_name: collection.name,
        write_concern: write_concern,
        bypass_document_validation: !!opts[:bypass_document_validation],
        session: session,
        let: opts[:let],
        comment: opts[:comment]
      ).execute_with_connection(connection, context: context)
    end
  end
end

#update_one(spec, opts = {}) ⇒ Result

Update a single document in the collection.

Examples:

Update a single document in the collection.

collection_view.update_one('$set' => { name: 'test' })

Parameters:

  • spec (Hash | Array<Hash>)

    The update document or pipeline.

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

    The options.

  • options (Hash)

    a customizable set of options

Options Hash (opts):

  • :array_filters (Array)

    A set of filters specifying to which array elements an update should apply.

  • :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.

  • :hint (Hash | String)

    The index to use for this operation. May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. “id”).

  • :let (Hash)

    Mapping of variables to use in the command. See the server documentation for details.

  • :session (Session)

    The session to use.

  • :upsert (true, false)

    Whether to upsert if the document doesn’t exist.

  • :write_concern (Hash)

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

  • :sort (Hash)

    Specifies which document the operation updates if the query matches multiple documents. The first document matched by the sort order will be updated. This option is only supported by servers >= 8.0. Older servers will report an error for using this option.

Returns:

  • (Result)

    The response from the database.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/writable.rb', line 566

def update_one(spec, opts = {})
  with_session(opts) do |session|
    write_concern = if opts[:write_concern]
                      WriteConcern.get(opts[:write_concern])
                    else
                      write_concern_with_session(session)
                    end
    validate_update_documents!(spec)

    QueryCache.clear_namespace(collection.namespace)

    update_doc = {
      Operation::Q => filter,
      arrayFilters: opts[:array_filters] || opts['array_filters'],
      Operation::U => spec,
      hint: opts[:hint],
      collation: opts[:collation] || opts['collation'] || collation,
      sort: opts[:sort] || opts['sort'],
    }.compact
    update_doc['upsert'] = true if opts[:upsert]

    context = Operation::Context.new(
      client: client,
      session: session,
      operation_timeouts: operation_timeouts(opts)
    )
    operation = Operation::Update.new(
      updates: [ update_doc ],
      db_name: collection.database.name,
      coll_name: collection.name,
      write_concern: write_concern,
      bypass_document_validation: !!opts[:bypass_document_validation],
      session: session,
      let: opts[:let],
      comment: opts[:comment]
    )
    tracer.trace_operation(operation, context) do
      write_with_retry(write_concern, context: context) do |connection, txn_num, context|
        gte_4_2 = connection.server.description.server_version_gte?('4.2')
        if !gte_4_2 && opts[:hint] && write_concern && !write_concern.acknowledged?
          raise Error::UnsupportedOption.hint_error(unacknowledged_write: true)
        end

        operation.txn_num = txn_num
        operation.execute_with_connection(connection, context: context)
      end
    end
  end
end

#validate_replacement_documents!(spec) (private)

Check the replacement documents to make sure they don’t have atomic modifiers. Note that as per the spec, we only have to examine the first element in the replacement document.

Parameters:

  • spec (Hash | Array<Hash>)

    The replacement document or pipeline.

Raises:

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/writable.rb', line 643

def validate_replacement_documents!(spec)
  return unless replace = spec.is_a?(Array) ? spec&.first : spec
  return unless key = replace.keys&.first
  return unless key.to_s.start_with?('$')
  raise Error::InvalidReplacementDocument.new(key: key) if Mongo.validate_update_replace

  Error::InvalidReplacementDocument.warn(Logger.logger, key)
end

#validate_update_documents!(spec) (private)

Checks the update documents to make sure they only have atomic modifiers. Note that as per the spec, we only have to examine the first element in the update document.

Parameters:

  • spec (Hash | Array<Hash>)

    The update document or pipeline.

Raises:

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/writable.rb', line 626

def validate_update_documents!(spec)
  return unless update = spec.is_a?(Array) ? spec&.first : spec
  return unless key = update.keys&.first
  return if key.to_s.start_with?('$')
  raise Error::InvalidUpdateDocument.new(key: key) if Mongo.validate_update_replace

  Error::InvalidUpdateDocument.warn(Logger.logger, key)
end