Class: Mongo::Collection

Inherits:
Object show all
Includes:
JavaImpl::Collection_, JavaImpl::Utils
Defined in:
lib/jmongo/collection.rb

Constant Summary

Constants included from JavaImpl::Utils

JavaImpl::Utils::SortingHash

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from JavaImpl::Utils

#from_dbobject, #prep_fields, #prep_sort, #raise_not_implemented, #sort_value, #to_dbobject, #trap_raise

Constructor Details

#initialize(*args) ⇒ Collection

Initialize a collection object.

db, name, options=nil, j_collection=nil

Parameters:

  • db (DB)

    a MongoDB database instance.

  • name (String, Symbol)

    the name of the collection.

Raises:

  • (InvalidNSName)

    if collection name is empty, contains ‘$’, or starts or ends with ‘.’

  • (TypeError)

    if collection name is not a string or symbol



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/jmongo/collection.rb', line 39

def initialize(*args)
  j_collection = nil
  @opts = {}
  if args.size == 4
    j_collection = args.pop
  end
  if args.size == 3
    @opts = args.pop
  end
  if args.size < 2
    raise ArgumentError.new("Must supply at least name and db parameters")
  end
  if args.first.respond_to?('collection_names')
    db, name = args
  else
    name, db = args
  end

  @name = validate_name(name)
  @db, @j_db  = db, db.j_db
  @connection = @db.connection
  @pk_factory = @opts[:pk] || BSON::ObjectId
  @hint = nil
  @j_collection = j_collection || @j_db.get_collection(@name)
end

Instance Attribute Details

#dbObject (readonly)

Returns the value of attribute db.



22
23
24
# File 'lib/jmongo/collection.rb', line 22

def db
  @db
end

#hintObject

Returns the value of attribute hint.



22
23
24
# File 'lib/jmongo/collection.rb', line 22

def hint
  @hint
end

#j_collectionObject (readonly)

Returns the value of attribute j_collection.



21
22
23
# File 'lib/jmongo/collection.rb', line 21

def j_collection
  @j_collection
end

#j_dbObject (readonly)

Returns the value of attribute j_db.



21
22
23
# File 'lib/jmongo/collection.rb', line 21

def j_db
  @j_db
end

#nameObject (readonly)

Returns the value of attribute name.



22
23
24
# File 'lib/jmongo/collection.rb', line 22

def name
  @name
end

#pk_factoryObject (readonly)

Returns the value of attribute pk_factory.



22
23
24
# File 'lib/jmongo/collection.rb', line 22

def pk_factory
  @pk_factory
end

Instance Method Details

#[](name) ⇒ Collection

Return a sub-collection of this collection by name. If ‘users’ is a collection, then ‘users.comments’ is a sub-collection of users.

Parameters:

  • name (String)

    the collection to return

Returns:

Raises:



76
77
78
79
80
# File 'lib/jmongo/collection.rb', line 76

def [](name)
  new_name = "#{self.name}.#{name}"
  validate_name new_name
  @db.create_collection(new_name, @opts)
end

#capped?Boolean

Returns:

  • (Boolean)


82
83
84
# File 'lib/jmongo/collection.rb', line 82

def capped?
  @j_collection.isCapped
end

#count(opts = {}) ⇒ Integer Also known as: size

Get the number of documents in this collection.

Returns:

  • (Integer)


625
626
627
628
629
630
631
632
# File 'lib/jmongo/collection.rb', line 625

def count(opts={})
  return @j_collection.count() if opts.empty?
  query = opts[:query] || opts['query'] || {}
  fields = opts[:fields] || opts['fields'] || {}
  limit = opts[:limit] || opts['limit'] || 0
  skip = opts[:skip] || opts['skip'] || 0
  @j_collection.get_count(to_dbobject(query), to_dbobject(fields), limit, skip)
end

#create_index(spec, opts = {}) ⇒ String Also known as: ensure_index

Create a new index.

Examples:

Creating a compound index:

@posts.create_index([['subject', Mongo::ASCENDING], ['created_at', Mongo::DESCENDING]])

Creating a geospatial index:

@restaurants.create_index([['location', Mongo::GEO2D]])

# Note that this will work only if 'location' represents x,y coordinates:
{'location': [0, 50]}
{'location': {'x' => 0, 'y' => 50}}
{'location': {'latitude' => 0, 'longitude' => 50}}

A geospatial index with alternate longitude and latitude:

@restaurants.create_index([['location', Mongo::GEO2D]], :min => 500, :max => 500)

Parameters:

  • spec (String, Array)

    should be either a single field name or an array of

    field name, direction

    pairs. Directions should be specified

    as Mongo::ASCENDING, Mongo::DESCENDING, or Mongo::GEO2D.

    Note that geospatial indexing only works with versions of MongoDB >= 1.3.3+. Keep in mind, too, that in order to geo-index a given field, that field must reference either an array or a sub-object where the first two values represent x- and y-coordinates. Examples can be seen below.

    Also note that it is permissible to create compound indexes that include a geospatial index as long as the geospatial index comes first.

  • unique (Boolean)

    if true, this index will enforce a uniqueness constraint. DEPRECATED. Future versions of this driver will specify the uniqueness constraint using a hash param.

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

    a customizable set of options

Options Hash (opts):

  • :unique (Boolean) — default: false

    if true, this index will enforce a uniqueness constraint.

  • :background (Boolean) — default: false

    indicate that the index should be built in the background. This feature is only available in MongoDB >= 1.3.2.

  • :dropDups (Boolean)

    If creating a unique index on a collection with pre-existing records, this option will keep the first document the database indexes and drop all subsequent with duplicate values.

  • :min (Integer)

    specify the minimum longitude and latitude for a geo index.

  • :max (Integer)

    specify the maximum longitude and latitude for a geo index.

Returns:

  • (String)

    the name of the index created.



341
342
343
# File 'lib/jmongo/collection.rb', line 341

def create_index(spec, opts={})
  _create_indexes(spec, opts)
end

#distinct(key, query = nil) ⇒ Array

Return a list of distinct values for key across all documents in the collection. The key may use dot notation to reach into an embedded object.

Examples:

Saving zip codes and ages and returning distinct results.

@collection.save({:zip => 10010, :name => {:age => 27}})
@collection.save({:zip => 94108, :name => {:age => 24}})
@collection.save({:zip => 10010, :name => {:age => 27}})
@collection.save({:zip => 99701, :name => {:age => 24}})
@collection.save({:zip => 94108, :name => {:age => 27}})

@collection.distinct(:zip)
  [10010, 94108, 99701]
@collection.distinct("name.age")
  [27, 24]

# You may also pass a document selector as the second parameter
# to limit the documents over which distinct is run:
@collection.distinct("name.age", {"name.age" => {"$gt" => 24}})
  [27]

Parameters:

  • key (String, Symbol, OrderedHash)

    or hash to group by.

  • query (Hash) (defaults to: nil)

    a selector for limiting the result set over which to group.

Returns:

  • (Array)

    an array of distinct values.

Raises:



568
569
570
571
572
573
574
575
# File 'lib/jmongo/collection.rb', line 568

def distinct(key, query=nil)
  raise MongoArgumentError unless [String, Symbol].include?(key.class)
  if query
    from_dbobject @j_collection.distinct(key.to_s, to_dbobject(query))
  else
    from_dbobject @j_collection.distinct(key.to_s)
  end
end

#dropObject

Drop the entire collection. USE WITH CAUTION.



368
369
370
# File 'lib/jmongo/collection.rb', line 368

def drop
  @j_collection.drop
end

#drop_index(spec) ⇒ Object

Drop a specified index.

Parameters:

  • spec (String, Array)

    should be either a single field name or an array of

    field name, direction

    pairs. Directions should be specified

    as Mongo::ASCENDING, Mongo::DESCENDING, or Mongo::GEO2D.

Raises:



354
355
356
357
# File 'lib/jmongo/collection.rb', line 354

def drop_index(spec)
  raise MongoArgumentError, "Cannot drop index for nil name" unless name
  _drop_index(spec)
end

#drop_indexesObject

Drop all indexes.



362
363
364
365
# File 'lib/jmongo/collection.rb', line 362

def drop_indexes
  # Note: calling drop_indexes with no args will drop them all.
  @j_collection.dropIndexes('*')
end

#find(selector = {}, opts = {}) ⇒ Object

Query the database.

The selector argument is a prototype document that all results must match. For example:

collection.find({"hello" => "world"})

only matches documents that have a key “hello” with value “world”. Matches can have other keys *in addition* to “hello”.

If given an optional block find will yield a Cursor to that block, close the cursor, and then return nil. This guarantees that partially evaluated cursors will be closed. If given no block find returns a cursor.

Parameters:

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

    a document specifying elements which must be present for a document to be included in the result set.

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

    a customizable set of options

Options Hash (opts):

  • :fields (Array, Hash)

    field names that should be returned in the result set (“_id” will always be included). By limiting results to a certain subset of fields, you can cut down on network traffic and decoding time. If using a Hash, keys should be field names and values should be either 1 or 0, depending on whether you want to include or exclude the given field.

  • :skip (Integer)

    number of documents to skip from the beginning of the result set

  • :limit (Integer)

    maximum number of documents to return

  • :sort (Array)

    an array of [key, direction] pairs to sort by. Direction should be specified as Mongo::ASCENDING (or :ascending / :asc) or Mongo::DESCENDING (or :descending / :desc)

  • :hint (String, Array, OrderedHash)

    hint for query optimizer, usually not necessary if using MongoDB > 1.1

  • :snapshot (Boolean) — default: 'false'

    if true, snapshot mode will be used for this query. Snapshot mode assures no duplicates are returned, or objects missed, which were preset at both the start and end of the query’s execution. For details see www.mongodb.org/display/DOCS/How+to+do+Snapshotting+in+the+Mongo+Database

  • :batch_size (Boolean) — default: 100

    the number of documents to returned by the database per GETMORE operation. A value of 0 will let the database server decide how many results to returns. This option can be ignored for most use cases.

  • :timeout (Boolean) — default: 'true'

    when true, the returned cursor will be subject to the normal cursor timeout behavior of the mongod process. When false, the returned cursor will never timeout. Note that disabling timeout will only work when #find is invoked with a block. This is to prevent any inadvertant failure to close the cursor, as the cursor is explicitly closed when block code finishes.

Raises:

  • (ArgumentError)

    if timeout is set to false and find is not invoked in a block

  • (RuntimeError)

    if given unknown options



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/jmongo/collection.rb', line 140

def find(selector={}, opts={})
  fields = prep_fields(opts.delete(:fields))
  skip   = opts.delete(:skip) || skip || 0
  limit  = opts.delete(:limit) || 0
  sort   = opts.delete(:sort)
  hint   = opts.delete(:hint)
  snapshot = opts.delete(:snapshot)
  batch_size = opts.delete(:batch_size)
  timeout    = (opts.delete(:timeout) == false) ? false : true
  transformer = opts.delete(:transformer)
  if timeout == false && !block_given?
    raise ArgumentError, "Timeout can be set to false only when #find is invoked with a block."
  end

  if hint
    hint = normalize_hint_fields(hint)
  else
    hint = @hint        # assumed to be normalized already
  end

  raise RuntimeError, "Unknown options [#{opts.inspect}]" unless opts.empty?

  cursor = Cursor.new(self, :selector => selector, :fields => fields, :skip => skip, :limit => limit,
                            :order => sort, :hint => hint, :snapshot => snapshot,
                            :batch_size => batch_size, :timeout => timeout,
                            :transformer => transformer)
  if block_given?
    yield cursor
    cursor.close
    nil
  else
    cursor
  end
end

#find_and_modify(opts = {}) ⇒ Hash

Atomically update and return a document using MongoDB’s findAndModify command. (MongoDB > 1.3.0)

Parameters:

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

    a customizable set of options

Options Hash (opts):

  • :update (Hash) — default: nil

    the update operation to perform on the matched document.

  • :query (Hash) — default: {}

    a query selector document for matching the desired document.

  • :sort (Array, String, OrderedHash) — default: {}

    specify a sort option for the query using any of the sort options available for Cursor#sort. Sort order is important if the query will be matching multiple documents since only the first matching document will be updated and returned.

  • :remove (Boolean) — default: false

    If true, removes the the returned document from the collection.

  • :new (Boolean) — default: false

    If true, returns the updated document; otherwise, returns the document prior to update.

Returns:

  • (Hash)

    the matched document.



387
388
389
390
391
392
393
394
395
396
397
398
# File 'lib/jmongo/collection.rb', line 387

def find_and_modify(opts={})
  query  = opts[:query] || {}
  fields = opts[:fields] || {}
  sort   = prep_sort(opts[:sort] || [])
  update = opts[:update] || {}
  remove = opts[:remove] || false
  new_    = opts[:new] || false
  upsert = opts[:upsert] || false
  trap_raise(OperationFailure) do
    find_and_modify_document(query, fields, sort, remove, update, new_, upsert)
  end
end

#find_one(spec_or_object_id = nil, opts = {}) ⇒ OrderedHash, Nil

Return a single object from the database.

Parameters:

  • spec_or_object_id (Hash, ObjectID, Nil) (defaults to: nil)

    a hash specifying elements which must be present for a document to be included in the result set or an instance of ObjectID to be used as the value for an _id query. If nil, an empty selector, {}, will be used.

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

    a customizable set of options

Options Hash (opts):

  • any (Hash)

    valid options that can be send to Collection#find

Returns:

  • (OrderedHash, Nil)

    a single document or nil if no result is found.

Raises:

  • (TypeError)

    if the argument is of an improper type.



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/jmongo/collection.rb', line 190

def find_one(spec_or_object_id=nil, opts={})
  spec = case spec_or_object_id
         when nil
           {}
         when BSON::ObjectId
           {'_id' => spec_or_object_id}
         when Hash
           spec_or_object_id
         else
           raise TypeError, "spec_or_object_id must be an instance of ObjectId or Hash, or nil"
         end
  begin
    find_one_document(spec, opts)
  rescue => ex
    raise OperationFailure, ex.message
  end
end

#group(opts, condition = {}, initial = {}, reduce = nil, finalize = nil) ⇒ Array

Perform a group aggregation.

Parameters:

  • opts (Hash)

    the options for this group operation. The minimum required are :initial and :reduce.

Options Hash (opts):

  • :key (Array, String, Symbol) — default: nil

    Either the name of a field or a list of fields to group by (optional).

  • :keyf (String, BSON::Code) — default: nil

    A JavaScript function to be used to generate the grouping keys (optional).

  • :cond (String, BSON::Code) — default: {}

    A document specifying a query for filtering the documents over which the aggregation is run (optional).

  • :initial (Hash)

    the initial value of the aggregation counter object (required).

  • :reduce (String, BSON::Code) — default: nil

    a JavaScript aggregation function (required).

  • :finalize (String, BSON::Code) — default: nil

    a JavaScript function that receives and modifies each of the resultant grouped objects. Available only when group is run with command set to true.

Returns:

  • (Array)

    the command response consisting of grouped items.

Raises:



486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
# File 'lib/jmongo/collection.rb', line 486

def group(opts, condition={}, initial={}, reduce=nil, finalize=nil)
  key = keyf = false
  if opts.is_a?(Hash)
    reduce, finalize, initial= opts.values_at(:reduce, :finalize, :initial)
    key, keyf = opts.values_at(:key, :keyf)
    condition = opts.fetch(:cond, {})
    unless key.nil? && keyf.nil?
      unless key.is_a?(Array) || keyf.is_a?(String) || keyf.is_a?(BSON::Code)
        raise MongoArgumentError, "Group takes either an array of fields to group by or a JavaScript function" +
          "in the form of a String or BSON::Code."
      end
    end
  else
    warn "Collection#group no longer take a list of parameters. This usage is deprecated and will be remove in v2.0." +
         "Check out the new API at http://api.mongodb.org/ruby/current/Mongo/Collection.html#group-instance_method"
    case opts
    when Array
      key = opts
    when String, BSON::Code
      keyf = opts
    else
      raise MongoArgumentError, "Group takes either an array of fields to group by or a JavaScript function" +
      "in the form of a String or BSON::Code."
    end
  end

  if !(reduce && initial)
    raise MongoArgumentError, "Group requires at minimum values for initial and reduce."
  end

  cmd = {
    "group" => {
      "ns"      => @name,
      "$reduce" => reduce.to_bson_code,
      "cond"    => condition,
      "initial" => initial
    }
  }

  if keyf
    cmd["group"]["$keyf"] = keyf.to_bson_code
  elsif key
    key_hash = Hash[key.zip( [1]*key.size )]
    cmd["group"]["key"] = key_hash
  end

  if finalize
    cmd['group']['finalize'] = finalize.to_bson_code
  end

  result = from_dbobject(@db.command(cmd))

  return result["retval"] if Mongo.result_ok?(result)

  raise OperationFailure, "group command failed: #{result['errmsg']}"
end

#index_informationHash

Get information on the indexes for this collection.

Returns:

  • (Hash)

    a hash where the keys are index names.



601
602
603
# File 'lib/jmongo/collection.rb', line 601

def index_information
  @db.index_information(@name)
end

#insert(doc_or_docs, options = {}) ⇒ ObjectID, Array Also known as: <<

Insert one or more documents into the collection.

Parameters:

  • doc_or_docs (Hash, Array)

    a document (as a hash) or array of documents to be inserted.

  • opts (Hash)

    a customizable set of options

Returns:

  • (ObjectID, Array)

    the _id of the inserted document or a list of _ids of all inserted documents. Note: the object may have been modified by the database’s PK factory, if it has one.



240
241
242
243
244
245
246
# File 'lib/jmongo/collection.rb', line 240

def insert(doc_or_docs, options={})
  doc_or_docs = [doc_or_docs] unless doc_or_docs.kind_of?(Array)
  doc_or_docs.collect! { |doc| @pk_factory.create_pk(doc) }
  continue = (options[:continue_on_error] || false)
  docs = insert_documents(doc_or_docs, options[:safe], continue)
  docs.size == 1 ? docs.first['_id'] : docs.collect{|doc| doc['_id']}
end

#map_reduce(map, reduce, opts = {}) ⇒ Collection Also known as: mapreduce

Perform a map/reduce operation on the current collection.

Parameters:

  • map (String, BSON::Code)

    a map function, written in JavaScript.

  • reduce (String, BSON::Code)

    a reduce function, written in JavaScript.

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

    a customizable set of options

Options Hash (opts):

  • :query (Hash) — default: {}

    a query selector document, like what’s passed to #find, to limit the operation to a subset of the collection.

  • :sort (Array) — default: []

    an array of [key, direction] pairs to sort by. Direction should be specified as Mongo::ASCENDING (or :ascending / :asc) or Mongo::DESCENDING (or :descending / :desc)

  • :limit (Integer) — default: nil

    if passing a query, number of objects to return from the collection.

  • :finalize (String, BSON::Code) — default: nil

    a javascript function to apply to the result set after the map/reduce operation has finished.

  • :out (String) — default: nil

    the name of the output collection. If specified, the collection will not be treated as temporary.

  • :keeptemp (Boolean) — default: false

    if true, the generated collection will be persisted. default is false.

  • :verbose (Boolean) — default: false

    if true, provides statistics on job execution time.

Returns:

  • (Collection)

    a collection containing the results of the operation.

See Also:



421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
# File 'lib/jmongo/collection.rb', line 421

def map_reduce(map, reduce, opts={})
  query = opts.fetch(:query,{})
  sort = opts.fetch(:sort,[])
  limit = opts.fetch(:limit,0)
  finalize = opts[:finalize]
  out = opts[:out]
  keeptemp = opts.fetch(:keeptemp,true)
  verbose = opts.fetch(:verbose,true)
  raw     = opts.delete(:raw)

  m = map.to_s
  r = reduce.to_s

  mrc = case out
      when String
        JMongo::MapReduceCommand.new(@j_collection, m, r, out, REPLACE, to_dbobject(query))
      when Hash
        if out.keys.size != 1
          raise ArgumentError, "You need to specify one key value pair in the out hash"
        end
        out_type = out.keys.first
        out_val = out[out_type]
        unless MapReduceEnumHash.keys.include?(out_type)
          raise ArgumentError, "Your out hash must have one of these keys: #{MapReduceEnumHash.keys}"
        end
        out_type_enum = MapReduceEnumHash[out_type]
        out_dest = out_val.is_a?(String) ? out_val : nil
        JMongo::MapReduceCommand.new(@j_collection, m, r, out_dest, out_type_enum, to_dbobject(query))
      else
        raise ArgumentError, "You need to specify an out parameter in the options hash"
      end

  mrc.verbose = verbose
  mrc.sort = prep_sort(sort)
  mrc.limit = limit
  mrc.finalize = finalize
  result =  from_dbobject(@j_db.command(mrc.toDBObject))

  if raw
    result
  elsif result["result"]
    @db[result["result"]]
  else
    raise ArgumentError, "Could not instantiate collection from result. If you specified " +
      "{:out => {:inline => true}}, then you must also specify :raw => true to get the results."
  end
end

#optionsHash

Return a hash containing options that apply to this collection. For all possible keys and values, see DB#create_collection.

Returns:

  • (Hash)

    options that apply to this collection.



609
610
611
612
613
# File 'lib/jmongo/collection.rb', line 609

def options
  info = @db.collections_info(@name).to_a
  ap info
  info.last['options']
end

#remove(selector = {}, options = {}) ⇒ True

Remove all documents from this collection.

Examples:

remove all documents from the ‘users’ collection:

users.remove
users.remove({})

remove only documents that have expired:

users.remove({:expire => {"$lte" => Time.now}})

Parameters:

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

    If specified, only matching documents will be removed.

  • opts (Hash)

    a customizable set of options

Returns:

  • (True)

Raises:



270
271
272
# File 'lib/jmongo/collection.rb', line 270

def remove(selector={}, options={})
  remove_documents(selector,options[:safe])
end

#rename(new_name) ⇒ Object

Rename this collection.

Note: If operating in auth mode, the client must be authorized as an admin to perform this operation.

Parameters:

  • new_name (String)

    the new name for this collection

Raises:



585
586
587
588
589
590
591
592
593
594
# File 'lib/jmongo/collection.rb', line 585

def rename(new_name)
  name = validate_name(new_name)
  begin
    jcol = @j_collection.rename(name)
    @name = name
    @j_collection = jcol
  rescue => ex
    raise MongoDBError, "Error renaming collection: #{name}, more: #{ex.message}"
  end
end

#save(doc, options = {}) ⇒ ObjectID

Save a document to this collection.

Parameters:

  • doc (Hash)

    the document to be saved. If the document already has an ‘_id’ key, then an update (upsert) operation will be performed, and any existing document with that _id is overwritten. Otherwise an insert operation is performed.

  • opts (Hash)

    a customizable set of options

Returns:

  • (ObjectID)

    the _id of the saved document.



221
222
223
# File 'lib/jmongo/collection.rb', line 221

def save(doc, options={})
  save_document(doc, options[:safe])
end

#statsHash

Return stats on the collection. Uses MongoDB’s collstats command.

Returns:



618
619
620
# File 'lib/jmongo/collection.rb', line 618

def stats
  @db.command({:collstats => @name})
end

#update(selector, document, options = {}) ⇒ Object

Update a single document in this collection.

Parameters:

  • selector (Hash)

    a hash specifying elements which must be present for a document to be updated. Note: the update command currently updates only the first document matching the given selector. If you want all matching documents to be updated, be sure to specify :multi => true.

  • document (Hash)

    a hash specifying the fields to be changed in the selected document, or (in the case of an upsert) the document to be inserted

  • [Boolean] (Hash)

    a customizable set of options

  • opts (Hash)

    a customizable set of options



294
295
296
297
# File 'lib/jmongo/collection.rb', line 294

def update(selector, document, options={})
  upsert, multi = !!(options[:upsert]), !!(options[:multi])
  update_documents(selector, document, upsert, multi, options[:safe])
end