Class: EM::Mongo::Collection

Inherits:
Object
  • Object
show all
Defined in:
lib/em-mongo/prev.rb,
lib/em-mongo/collection.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(db, ns, connection = nil) ⇒ Collection

Initialize a collection object.



12
13
14
15
16
17
# File 'lib/em-mongo/collection.rb', line 12

def initialize(db, ns, connection = nil)
  @db = db || "db"
  @ns = ns || "ns"
  @name = [@db,@ns].join('.')
  @connection = connection || EM::Mongo::Connection.new
end

Instance Attribute Details

#connectionObject

Returns the value of attribute connection



3
4
5
# File 'lib/em-mongo/collection.rb', line 3

def connection
  @connection
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.



39
40
41
42
# File 'lib/em-mongo/collection.rb', line 39

def [](name)
  name = "#{self.name}.#{name}"
  db.collection(name)
end

#countEM::Mongo::RequestResponse Also known as: size

Get the number of documents in this collection.



574
575
576
# File 'lib/em-mongo/collection.rb', line 574

def count
  find().count
end

#create_index(spec, opts = {}) ⇒ String

Returns the name of the index created.

Examples:

Creating a compound index:

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

Creating a geospatial index:

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

# 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', EM::Mongo::SPHERE2D]], :min => 500, :max => 500)

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.

  • :drop_dups (Boolean) — default: nil

    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) — default: nil

    specify the minimum longitude and latitude for a geo index.

  • :max (Integer) — default: nil

    specify the maximum longitude and latitude for a geo index.



640
641
642
643
644
645
646
647
648
# File 'lib/em-mongo/collection.rb', line 640

def create_index(spec, opts={})
  field_spec = parse_index_spec(spec)
  opts = opts.dup
  name = opts.delete(:name) || generate_index_name(field_spec)
  name = name.to_s if name

  generate_indexes(field_spec, name, opts)
  name
end

#dbEM::Mongo::Database

The database that this collection belongs to



21
22
23
# File 'lib/em-mongo/collection.rb', line 21

def db
  connection.db(@db)
end

#distinct(key, query = nil) ⇒ EM::Mongo::RequestResponse

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]

Raises:



491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
# File 'lib/em-mongo/collection.rb', line 491

def distinct(key, query=nil)
  raise MongoArgumentError unless [String, Symbol].include?(key.class)
  response = RequestResponse.new
  command = BSON::OrderedHash.new
  command[:distinct] = @ns
  command[:key]      = key.to_s
  command[:query]    = query

  cmd_resp = db.command(command)
  cmd_resp.callback do |resp|
    response.succeed resp["values"]
  end
  cmd_resp.errback do |err|
    response.fail err
  end
  response
end

#dropObject

Drop the entire collection. USE WITH CAUTION.



369
370
371
# File 'lib/em-mongo/collection.rb', line 369

def drop
  db.drop_collection(@ns)
end

#drop_index(name) ⇒ Object

Drop a specified index.



655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
# File 'lib/em-mongo/collection.rb', line 655

def drop_index(name)
  if name.is_a?(Array)
    response = RequestResponse.new
    name_resp = index_name(name)
    name_resp.callback do |name|
      drop_resp = db.drop_index(@ns, name)
      drop_resp.callback { response.succeed }
      drop_resp.errback { |err| response.fail(err) }
    end
    name_resp.errback { |err| response.fail(err) }
    response
  else
    db.drop_index(@ns, name)
  end
end

#drop_indexesObject

Drop all indexes.



674
675
676
677
# File 'lib/em-mongo/collection.rb', line 674

def drop_indexes
  # Note: calling drop_indexes with no args will drop them all.
  db.drop_index(@ns, '*')
end

#find(selector = {}, opts = {}) ⇒ EM::Mongo::Cursor

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”.

Options Hash (opts):

  • :fields (Array, Hash)

    field names that should be returned in the result set (“_id” will be included unless explicity excluded). 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. Disabling the timeout is not supported by em-mongo

  • :max_scan (Integer) — default: nil

    Limit the number of items to scan on both collection scans and indexed queries..

  • :show_disk_loc (Boolean) — default: false

    Return the disk location of each query result (for debugging).

  • :return_key (Boolean) — default: false

    Return the index key used to obtain the result (for debugging).

  • :transformer (Block) — default: nil

    a block for tranforming returned documents. This is normally used by object mappers to convert each returned document to an instance of a class.

Raises:

  • (ArgumentError)

    if timeout is set to false

  • (RuntimeError)

    if given unknown options



97
98
99
100
101
102
103
# File 'lib/em-mongo/collection.rb', line 97

def find(selector={}, opts={}, &blk)
  raise "find requires a block" if not block_given?

  new_find(selector, opts).defer_as_a.callback do |docs|
    blk.call(docs)
  end
end

#find_and_modify(opts = {}) ⇒ EM::Mongo::RequestResponse

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

Options Hash (opts):

  • :query (Hash) — default: {}

    a query selector document for matching the desired document.

  • :update (Hash) — default: nil

    the update operation to perform on the matched 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.



387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/em-mongo/collection.rb', line 387

def find_and_modify(opts={})
  response = RequestResponse.new
  cmd = BSON::OrderedHash.new
  cmd[:findandmodify] = @ns
  cmd.merge!(opts)
  cmd[:sort] = EM::Mongo::Support.format_order_clause(opts[:sort]) if opts[:sort]

  cmd_resp = db.command(cmd)
  cmd_resp.callback do |doc|
    response.succeed doc['value']
  end
  cmd_resp.errback do |err|
    response.fail err
  end
  response
end

#find_one(spec_or_object_id = nil, opts = {}) ⇒ EM::Mongo::RequestResponse Also known as: first

Return a single object from the database.

Options Hash (opts):

  • any (Hash)

    valid options that can be send to Collection#find

Raises:

  • (TypeError)

    if the argument is of an improper type.



155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/em-mongo/collection.rb', line 155

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
  find(spec, opts.merge(:limit => -1)).next_document
end

#group(opts = {}) ⇒ EM::Mongo::RequestResponse

Perform a group aggregation.

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.



525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
# File 'lib/em-mongo/collection.rb', line 525

def group(opts={})
  response = RequestResponse.new
  reduce   =  opts[:reduce]
  finalize =  opts[:finalize]
  cond     =  opts.fetch(:cond, {})
  initial  =  opts[:initial]

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

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

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

  if key = opts[:key]
    if key.is_a?(String) || key.is_a?(Symbol)
      key = [key]
    end
    key_value = {}
    key.each { |k| key_value[k] = 1 }
    cmd["group"]["key"] = key_value
  elsif keyf = opts[:keyf]
    cmd["group"]["$keyf"] = keyf.to_bson_code
  end

  cmd_resp = db.command(cmd)
  cmd_resp.callback do |result|
    response.succeed result["retval"]
  end
  cmd_resp.errback do |err|
    response.fail err
  end
  response
end

#index_informationEM::Mongo::RequestResponse

Get information on the indexes for this collection.



591
592
593
# File 'lib/em-mongo/collection.rb', line 591

def index_information
  db.index_information(@ns)
end

#insert(doc_or_docs) ⇒ ObjectId, Array Also known as: <<

Insert one or more documents into the collection.

See Also:

  • for options that can be passed to :safe.


181
182
183
# File 'lib/em-mongo/collection.rb', line 181

def insert(doc_or_docs)
  safe_insert(doc_or_docs, :safe => false).data
end

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

Perform a map-reduce operation on the current collection.

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

    a valid output type. In versions of MongoDB prior to v1.7.6, this option takes the name of a collection for the output results. In versions 1.7.6 and later, this option specifies the output type. See the core docs for available output types.

  • :keeptemp (Boolean) — default: false

    if true, the generated collection will be persisted. The defualt is false. Note that this option has no effect is versions of MongoDB > v1.7.6.

  • :verbose (Boolean) — default: false

    if true, provides statistics on job execution time.

  • :raw (Boolean) — default: false

    if true, return the raw result object from the map_reduce command, and not the instantiated collection that's returned by default. Note if a collection name isn't returned in the map-reduce output (as, for example, when using :out => => 1), then you must specify this option or an ArgumentError will be raised.

Raises:

  • ArgumentError if you specify => {:inline => true} but don't specify :raw => true.

See Also:



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
# File 'lib/em-mongo/collection.rb', line 434

def map_reduce(map, reduce, opts={})
  response = RequestResponse.new
  map    = BSON::Code.new(map) unless map.is_a?(BSON::Code)
  reduce = BSON::Code.new(reduce) unless reduce.is_a?(BSON::Code)
  raw    = opts.delete(:raw)

  hash = BSON::OrderedHash.new
  hash['mapreduce'] = @ns
  hash['map'] = map
  hash['reduce'] = reduce
  hash.merge! opts

  cmd_resp = db.command(hash)
  cmd_resp.callback do |result|
    if EM::Mongo::Support.ok?(result) == false
      response.fail [Mongo::OperationFailure, "map-reduce failed: #{result['errmsg']}"]
    elsif raw
      response.succeed result
    elsif result["result"]
      response.succeed db.collection(result["result"])
    else
      response.fail [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
  cmd_resp.errback do |err|
    response.fail(err)
  end
  response
end

#nameString

The name of this collection



27
28
29
# File 'lib/em-mongo/collection.rb', line 27

def name
  @ns
end

#new_findObject



5
# File 'lib/em-mongo/prev.rb', line 5

alias :new_find :find

#remove(selector = {}, opts = {}) ⇒ 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}})

Options Hash (opts):

  • :safe (Boolean, Hash) — default: +false+

    run the operation in safe mode, which will run a getlasterror command on the database to report any assertion. In addition, a hash can be provided to run an fsync and/or wait for replication of the remove (>= 1.5.1). Safe options provided here will override any safe options set on this collection, its database, or the current connection. See the options for DB#get_last_error for more details.

See Also:

  • for options that can be passed to :safe.


358
359
360
361
362
363
364
365
366
# File 'lib/em-mongo/collection.rb', line 358

def remove(selector={}, opts={})
  # Initial byte is 0.
  message = BSON::ByteBuffer.new("\0\0\0\0")
  BSON::BSON_RUBY.serialize_cstr(message, "#{@db}.#{@ns}")
  message.put_int(0)
  message.put_binary(BSON::BSON_CODER.serialize(selector, false, true).to_s)
  @connection.send_command(EM::Mongo::OP_DELETE, message)
  true
end

#safe_insert(doc_or_docs, safe_opts = {}) ⇒ EM::Mongo::RequestResponse

Insert one or more documents into the collection, with a failure if the operation doesn't succeed Unlike insert, this method returns a deferrable

See Also:

  • for options that can be passed to :safe.


206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/em-mongo/collection.rb', line 206

def safe_insert(doc_or_docs, safe_opts = {})
  response = RequestResponse.new
  safe_opts[:safe] = true unless safe_opts[:safe] == false
  doc_or_docs = [doc_or_docs] unless doc_or_docs.is_a?(Array)
  doc_or_docs.map! { |doc| sanitize_id!(doc) }
  insert_resp = insert_documents(doc_or_docs, @ns, true, safe_opts)
  insert_resp.callback do |ids|
    ids.length > 1 ? response.succeed(ids) : response.succeed(ids[0])
  end
  insert_resp.errback do |err|
    response.fail err
  end
  response
end

#safe_save(doc, opts = {}) ⇒ EM::Mongo::RequestResponse

Returns Calls backw with the _id of the saved document.

Options Hash (opts):

  • :safe (Boolean, Hash) — default: +true+

    run the operation in safe mode, which run a getlasterror command on the database to report any assertion. In addition, a hash can be provided to run an fsync and/or wait for replication of the save (>= 1.5.1). See the options for DB#error.



323
324
325
326
327
328
329
330
331
332
# File 'lib/em-mongo/collection.rb', line 323

def safe_save(doc, opts={})
  opts[:safe] = true unless opts[:safe] == false
  id = has_id?(doc)
  sanitize_id!(doc)
  if id
    safe_update({:_id => id}, doc, opts.merge(:upsert => true))
  else
    safe_insert(doc, opts)
  end
end

#safe_update(selector, document, opts = {}) ⇒ Hash, true

Returns a Hash containing the last error object if running in safe mode. Otherwise, returns true.

Options Hash (opts):

  • :upsert (Boolean) — default: +false+

    if true, performs an upsert (update or insert)

  • :multi (Boolean) — default: +false+

    update all documents matching the selector, as opposed to just the first matching document. Note: only works in MongoDB 1.1.3 or later.

  • :safe (Boolean) — default: +true+

    If true, check that the save succeeded. OperationFailure will be raised on an error. Note that a safe check requires an extra round-trip to the database. Safe options provided here will override any safe options set on this collection, its database object, or the current collection. See the options for DB#get_last_error for details.



270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
# File 'lib/em-mongo/collection.rb', line 270

def safe_update(selector, document, opts={})
  response = RequestResponse.new
  opts = opts.dup
  opts[:safe] = true unless opts[:safe] == false
  # Initial byte is 0.
  message = BSON::ByteBuffer.new("\0\0\0\0")
  BSON::BSON_RUBY.serialize_cstr(message, "#{@db}.#{@ns}")
  update_options  = 0
  update_options += 1 if opts.delete(:upsert)
  update_options += 2 if opts.delete(:multi)
  message.put_int(update_options)
  message.put_binary(BSON::BSON_CODER.serialize(selector, false, true).to_s)
  message.put_binary(BSON::BSON_CODER.serialize(document, false, true).to_s)

  if opts[:safe]
    send_resp = safe_send(EM::Mongo::OP_UPDATE, message, true, opts)
    send_resp.callback { response.succeed(true) }
    send_resp.errback { |err| response.fail(err) }
  else
    @connection.send_command(EM::Mongo::OP_UPDATE, message)
    response.succeed(true)
  end
  response
end

#save(doc, opts = {}) ⇒ ObjectId

Save a document to this collection.



304
305
306
# File 'lib/em-mongo/collection.rb', line 304

def save(doc, opts={})
  safe_save(doc, opts.merge(:safe => false)).data
end

#statsEM::Mongo::RequestResponse

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



582
583
584
# File 'lib/em-mongo/collection.rb', line 582

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

#update(selector, document, opts = {}) ⇒ Hash, true

Update one or more documents in this collection.

Options Hash (opts):

  • :upsert (Boolean) — default: +false+

    if true, performs an upsert (update or insert)

  • :multi (Boolean) — default: +false+

    update all documents matching the selector, as opposed to just the first matching document. Note: only works in MongoDB 1.1.3 or later.



240
241
242
243
# File 'lib/em-mongo/collection.rb', line 240

def update(selector, document, opts={})
  # Initial byte is 0.
  safe_update(selector, document, opts.merge(:safe => false)).data
end