class Mongo::Operation::Result

Result wrapper for wire protocol replies.

An operation has zero or one replies. The only operations producing zero replies are unacknowledged writes; all other operations produce one reply. This class provides an object that can be operated on (for example, to check whether an operation succeeded) even when the operation did not produce a reply (in which case it is assumed to have succeeded).

@since 2.0.0 @api semiprivate

Constants

CURSOR

The field name for the cursor document in an aggregation.

@since 2.2.0 @api private

CURSOR_ID

The cursor id field in the cursor document.

@since 2.2.0 @api private

FIRST_BATCH

The field name for the first batch of a cursor.

@since 2.2.0 @api private

N

The number of documents updated in the write.

@since 2.0.0 @api private

NAMESPACE

The namespace field in the cursor document.

@since 2.2.0 @api private

NEXT_BATCH

The field name for the next batch of a cursor.

@since 2.2.0 @api private

OK

The ok status field in the result.

@since 2.0.0 @api private

RESULT

The result field constant.

@since 2.2.0 @api private

Attributes

connection_description[R]

@return [ Server::Description ] Server description of the server that

the operation was performed on that this result is for.

@api private

replies[R]

@return [ Array<Protocol::Message> ] replies The wrapped wire protocol replies.

@api private

Public Class Methods

new(replies, connection_description = nil) click to toggle source

Initialize a new result.

For an unkacknowledged write, pass nil in replies.

For all other operations, replies must be a Protocol::Message instance or an array containing a single Protocol::Message instance.

@param [ Protocol::Message | Array<Protocol::Message> | nil ] replies

The wire protocol replies.

@param [ Server::Description | nil ] connection_description

Server description of the server that performed the operation that
this result is for. This parameter is allowed to be nil for
compatibility with existing mongo_kerberos library, but should
always be not nil in the driver proper.

@api private

# File lib/mongo/operation/result.rb, line 102
def initialize(replies, connection_description = nil)
  if replies
    if replies.is_a?(Array)
      if replies.length != 1
        raise ArgumentError, "Only one (or zero) reply is supported, given #{replies.length}"
      end
      reply = replies.first
    else
      reply = replies
    end
    unless reply.is_a?(Protocol::Message)
      raise ArgumentError, "Argument must be a Message instance, but is a #{reply.class}: #{reply.inspect}"
    end
    @replies = [ reply ]
    @connection_description = connection_description
  end
end

Public Instance Methods

acknowledged?() click to toggle source

Is the result acknowledged?

@note On MongoDB 2.6 and higher all writes are acknowledged since the

driver uses write commands for all write operations. On 2.4 and
lower, the result is acknowledged if the GLE has been executed after
the command. If not, no replies will be specified. Reads will always
return true here since a replies is always provided.

@return [ true, false ] If the result is acknowledged.

@since 2.0.0 @api public

# File lib/mongo/operation/result.rb, line 147
def acknowledged?
  !!@replies
end
cluster_time() click to toggle source

Get the cluster time reported in the server response.

@example Get the cluster time.

result.cluster_time

@return [ ClusterTime | nil ] The cluster time document.

Changed in version 2.9.0: This attribute became an instance of ClusterTime, which is a subclass of BSON::Document. Previously it was an instance of BSON::Document.

@since 2.5.0 @api public

# File lib/mongo/operation/result.rb, line 408
def cluster_time
  first_document && ClusterTime[first_document['$clusterTime']]
end
cursor_id() click to toggle source

Get the cursor id if the response is acknowledged.

@note Cursor ids of 0 indicate there is no cursor on the server.

@example Get the cursor id.

result.cursor_id

@return [ Integer ] The cursor id.

@since 2.0.0 @api private

# File lib/mongo/operation/result.rb, line 162
def cursor_id
  acknowledged? ? replies.last.cursor_id : 0
end
documents() click to toggle source

Get the documents in the result.

@example Get the documents.

result.documents

@return [ Array<BSON::Document> ] The documents.

@since 2.0.0 @api public

# File lib/mongo/operation/result.rb, line 186
def documents
  if acknowledged?
    replies.flat_map(&:documents)
  else
    []
  end
end
each(&block) click to toggle source

Iterate over the documents in the replies.

@example Iterate over the documents.

result.each do |doc|
  p doc
end

@return [ Enumerator ] The enumerator.

@yieldparam [ BSON::Document ] Each document in the result.

@since 2.0.0 @api public

# File lib/mongo/operation/result.rb, line 207
def each(&block)
  documents.each(&block)
end
error() click to toggle source

The exception instance (of the Error::OperationFailure class) that would be raised during processing of this result.

This method should only be called when result is not successful.

@return [ Error::OperationFailure ] The exception.

@api private

# File lib/mongo/operation/result.rb, line 325
def error
  @error ||= Error::OperationFailure.new(
    parser.message,
    self,
    code: parser.code,
    code_name: parser.code_name,
    write_concern_error_document: parser.write_concern_error_document,
    write_concern_error_code: parser.write_concern_error_code,
    write_concern_error_code_name: parser.write_concern_error_code_name,
    write_concern_error_labels: parser.write_concern_error_labels,
    labels: parser.labels,
    wtimeout: parser.wtimeout,
    connection_description: connection_description,
    document: parser.document,
    server_message: parser.server_message,
  )
end
inspect() click to toggle source

Get the pretty formatted inspection of the result.

@example Inspect the result.

result.inspect

@return [ String ] The inspection.

@since 2.0.0 @api public

# File lib/mongo/operation/result.rb, line 220
def inspect
  "#<#{self.class.name}:0x#{object_id} documents=#{documents}>"
end
labels() click to toggle source

Gets the set of error labels associated with the result.

@example Get the labels.

result.labels

@return [ Array ] labels The set of labels.

@since 2.7.0 @api private

# File lib/mongo/operation/result.rb, line 421
def labels
  @labels ||= parser.labels
end
n()

@api public

Alias for: written_count
namespace() click to toggle source

Get the namespace of the cursor. The method should be defined in result classes where ‘ns’ is in the server response.

@return [ Nil ]

@since 2.0.0 @api private

# File lib/mongo/operation/result.rb, line 173
def namespace
  nil
end
ok?() click to toggle source

Check the first document’s ok field.

@example Check the ok field.

result.ok?

@return [ true, false ] If the command returned ok.

@since 2.1.0 @api public

# File lib/mongo/operation/result.rb, line 289
def ok?
  # first_document[OK] is a float, and the server can return
  # ok as a BSON int32, BSON int64 or a BSON double.
  # The number 1 is exactly representable in a float, hence
  # 1.0 == 1 is going to perform correctly all of the time
  # (until the server returns something other than 1 for success, that is)
  first_document[OK] == 1
end
operation_time() click to toggle source

Get the operation time reported in the server response.

@example Get the operation time.

result.operation_time

@return [ Object | nil ] The operation time value.

@since 2.5.0 @api public

# File lib/mongo/operation/result.rb, line 391
def operation_time
  first_document && first_document[OPERATION_TIME]
end
reply() click to toggle source

Get the reply from the result.

Returns nil if there is no reply (i.e. the operation was an unacknowledged write).

@return [ Protocol::Message ] The first reply.

@since 2.0.0 @api private

# File lib/mongo/operation/result.rb, line 233
def reply
  if acknowledged?
    replies.first
  else
    nil
  end
end
returned_count() click to toggle source

Get the count of documents returned by the server.

@example Get the number returned.

result.returned_count

@return [ Integer ] The number of documents returned.

@since 2.0.0 @api public

# File lib/mongo/operation/result.rb, line 250
def returned_count
  if acknowledged?
    reply.number_returned
  else
    0
  end
end
snapshot_timestamp() click to toggle source
# File lib/mongo/operation/result.rb, line 432
def snapshot_timestamp
  if doc = reply.documents.first
    doc['cursor']&.[]('atClusterTime') || doc['atClusterTime']
  end
end
successful?() click to toggle source

If the result was a command then determine if it was considered a success.

@note If the write was unacknowledged, then this will always return

true.

@example Was the command successful?

result.successful?

@return [ true, false ] If the command was successful.

@since 2.0.0 @api public

# File lib/mongo/operation/result.rb, line 271
def successful?
  return true if !acknowledged?
  if first_document.has_key?(OK)
    ok? && parser.message.empty?
  else
    !query_failure? && parser.message.empty?
  end
end
topology_version() click to toggle source

@return [ TopologyVersion | nil ] The topology version.

@api private

# File lib/mongo/operation/result.rb, line 354
def topology_version
  unless defined?(@topology_version)
    @topology_version = first_document['topologyVersion'] &&
      TopologyVersion.new(first_document['topologyVersion'])
  end
  @topology_version
end
validate!() click to toggle source

Validate the result by checking for any errors.

@note This only checks for errors with writes since authentication is

handled at the connection level and any authentication errors would
be raised there, before a Result is ever created.

@example Validate the result.

result.validate!

@raise [ Error::OperationFailure ] If an error is in the result.

@return [ Result ] The result if verification passed.

@since 2.0.0 @api private

# File lib/mongo/operation/result.rb, line 313
def validate!
  !successful? ? raise_operation_failure : self
end
write_concern_error?() click to toggle source

Whether the operation failed with a write concern error.

@api private

# File lib/mongo/operation/result.rb, line 428
def write_concern_error?
  !!(first_document && first_document['writeConcernError'])
end
written_count() click to toggle source

Get the number of documents written by the server.

@example Get the number of documents written.

result.written_count

@return [ Integer ] The number of documents written.

@since 2.0.0 @api public

# File lib/mongo/operation/result.rb, line 371
def written_count
  if acknowledged?
    first_document[N] || 0
  else
    0
  end
end
Also aliased as: n

Private Instance Methods

aggregate_returned_count() click to toggle source
# File lib/mongo/operation/result.rb, line 440
def aggregate_returned_count
  replies.reduce(0) do |n, reply|
    n += reply.number_returned
    n
  end
end
aggregate_written_count() click to toggle source
# File lib/mongo/operation/result.rb, line 447
def aggregate_written_count
  documents.reduce(0) do |n, document|
    n += (document[N] || 0)
    n
  end
end
first_document() click to toggle source
# File lib/mongo/operation/result.rb, line 458
def first_document
  @first_document ||= first || BSON::Document.new
end
parser() click to toggle source
# File lib/mongo/operation/result.rb, line 454
def parser
  @parser ||= Error::Parser.new(first_document, replies)
end
query_failure?() click to toggle source
# File lib/mongo/operation/result.rb, line 462
def query_failure?
  replies.first && (replies.first.query_failure? || replies.first.cursor_not_found?)
end
raise_operation_failure() click to toggle source

Raises a Mongo::OperationFailure exception corresponding to the error information in this result.

@raise Error::OperationFailure

# File lib/mongo/operation/result.rb, line 347
        def raise_operation_failure
  raise error
end