Class: Mongoid::Contextual::Mongo

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Enumerable, Association::EagerLoadable, Atomic, Aggregable::Mongo, Queryable
Defined in:
build/mongoid-master/lib/mongoid/contextual/mongo.rb

Constant Summary collapse

OPTIONS =

Options constant.

[ :hint,
  :limit,
  :skip,
  :sort,
  :batch_size,
  :max_scan,
  :max_time_ms,
  :snapshot,
  :comment,
  :read,
  :cursor_type,
  :collation
].freeze

Constants included from Atomic

Atomic::UPDATES

Instance Attribute Summary collapse

Attributes included from Queryable

#collection, #collection The collection to query against., #criteria, #criteria The criteria for the context., #klass, #klass The klass for the criteria.

Instance Method Summary collapse

Methods included from Queryable

#blank?

Methods included from Association::EagerLoadable

#eager_load, #eager_loadable?, #preload

Methods included from Atomic

#add_atomic_pull, #add_atomic_unset, #atomic_array_add_to_sets, #atomic_array_pulls, #atomic_array_pushes, #atomic_attribute_name, #atomic_delete_modifier, #atomic_insert_modifier, #atomic_path, #atomic_paths, #atomic_position, #atomic_pulls, #atomic_pushes, #atomic_sets, #atomic_unsets, #atomic_updates, #delayed_atomic_pulls, #delayed_atomic_sets, #delayed_atomic_unsets, #flag_as_destroyed, #flagged_destroys, #process_flagged_destroys

Methods included from Aggregable::Mongo

#aggregates, #avg, #max, #min, #sum

Constructor Details

#initialize(criteria) ⇒ Mongo

Create the new Mongo context. This delegates operations to the underlying driver.

Examples:

Create the new context.

Mongo.new(criteria)

Parameters:



344
345
346
347
348
349
350
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 344

def initialize(criteria)
  @criteria, @klass, @cache = criteria, criteria.klass, criteria.options[:cache]
  @collection = @klass.collection
  criteria.send(:merge_type_selection)
  @view = collection.find(criteria.selector, session: _session)
  apply_options
end

Instance Attribute Details

#viewObject (readonly)

Returns the value of attribute view.



38
39
40
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 38

def view
  @view
end

#view The Mongo collection view.(TheMongocollectionview.) ⇒ Object (readonly)



38
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 38

attr_reader :view

Instance Method Details

#cached?true, false

Is the context cached?

Examples:

Is the context cached?

context.cached?

Returns:

  • (true, false)

    If the context is cached.



46
47
48
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 46

def cached?
  !!@cache
end

#count(options = {}, &block) ⇒ Integer

Get the number of documents matching the query.

Examples:

Get the number of matching documents.

context.count

Get the count of documents with the provided options.

context.count(limit: 1)

Get the count for where the provided block is true.

context.count do |doc|
  doc.likes > 1
end

Parameters:

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

    The options, such as skip and limit to be factored into the count.

Returns:

  • (Integer)

    The number of matches.



67
68
69
70
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 67

def count(options = {}, &block)
  return super(&block) if block_given?
  try_cache(:count) { view.count_documents(options) }
end

#deletenil Also known as: delete_all

Delete all documents in the database that match the selector.

Examples:

Delete all the documents.

context.delete

Returns:

  • (nil)

    Nil.



97
98
99
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 97

def delete
  view.delete_many.deleted_count
end

#destroynil Also known as: destroy_all

Destroy all documents in the database that match the selector.

Examples:

Destroy all the documents.

context.destroy

Returns:

  • (nil)

    Nil.



108
109
110
111
112
113
114
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 108

def destroy
  each.inject(0) do |count, doc|
    doc.destroy
    count += 1 if acknowledged_write?
    count
  end
end

#distinct(field) ⇒ Array<Object>

Get the distinct values in the db for the provided field.

Examples:

Get the distinct values.

context.distinct(:name)

Parameters:

  • field (String, Symbol)

    The name of the field.

Returns:

  • (Array<Object>)

    The distinct values for the field.



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 125

def distinct(field)
  name = if Mongoid.legacy_pluck_distinct
    klass.database_field_name(field)
  else
    klass.cleanse_localized_field_names(field)
  end

  view.distinct(name).map do |value|
    if Mongoid.legacy_pluck_distinct
      value.class.demongoize(value)
    else
      is_translation = "#{name}_translations" == field.to_s
      recursive_demongoize(name, value, is_translation)
    end
  end
end

#each(&block) ⇒ Enumerator

Iterate over the context. If provided a block, yield to a Mongoid document for each, otherwise return an enum.

Examples:

Iterate over the context.

context.each do |doc|
  puts doc.name
end

Returns:

  • (Enumerator)

    The enumerator.



151
152
153
154
155
156
157
158
159
160
161
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 151

def each(&block)
  if block_given?
    documents_for_iteration.each do |doc|
      yield_document(doc, &block)
    end
    @cache_loaded = true
    self
  else
    to_enum
  end
end

#estimated_count(options = {}) ⇒ Integer

Get the estimated number of documents matching the query.

Unlike count, estimated_count does not take a block because it is not traditionally defined (with a block) on Enumarable like count is.

Examples:

Get the estimated number of matching documents.

context.estimated_count

Parameters:

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

    The options, such as maxTimeMS to be factored into the count.

Returns:

  • (Integer)

    The number of matches.



84
85
86
87
88
89
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 84

def estimated_count(options = {})
  unless self.criteria.selector.empty?
    raise Mongoid::Errors::InvalidEstimatedCountCriteria.new(self.klass)
  end
  try_cache(:estimated_count) { view.estimated_document_count(options) }
end

#exists?true, false

Note:

We don't use count here since Mongo does not use counted b-tree indexes, unless a count is already cached then that is used to determine the value.

Do any documents exist for the context.

Examples:

Do any documents exist for the context.

context.exists?

Returns:

  • (true, false)

    If the count is more than zero.



173
174
175
176
177
178
179
180
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 173

def exists?
  return !documents.empty? if cached? && cache_loaded?
  return @count > 0 if instance_variable_defined?(:@count)

  try_cache(:exists) do
    !!(view.projection(_id: 1).limit(1).first)
  end
end

#explainHash

Run an explain on the criteria.

Examples:

Explain the criteria.

Band.where(name: "Depeche Mode").explain

Returns:

  • (Hash)

    The explain result.



188
189
190
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 188

def explain
  view.explain
end

#fetch_and_demongoize(d, meth, klass) ⇒ Object



706
707
708
709
710
711
712
713
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 706

def fetch_and_demongoize(d, meth, klass)
  res = d.try(:fetch, meth, nil)
  if field = klass.fields[meth]
    field.demongoize(res)
  else
    res.class.demongoize(res)
  end
end

#find_firstObject

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.

Return the first result without applying sort



283
284
285
286
287
288
289
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 283

def find_first
  return documents.first if cached? && cache_loaded?
  if raw_doc = view.first
    doc = Factory.from_db(klass, raw_doc, criteria)
    eager_load([doc]).first
  end
end

#find_one_and_deleteDocument

Execute the find and modify command, used for MongoDB's $findAndModify. This deletes the found document.

Examples:

Execute the command.

context.find_one_and_delete

Returns:

  • (Document)

    The result of the command.



239
240
241
242
243
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 239

def find_one_and_delete
  if doc = view.find_one_and_delete
    Factory.from_db(klass, doc)
  end
end

#find_one_and_replace(replacement, options = {}) ⇒ Document

Execute the find and modify command, used for MongoDB's $findAndModify.

Examples:

Execute the command.

context.find_one_and_update({ likes: 1 })

Parameters:

  • replacement (Hash)

    The replacement.

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

    The command options.

Options Hash (options):

  • :return_document (:before, :after)

    Return the updated document from before or after update.

  • :upsert (true, false)

    Create the document if it doesn't exist.

Returns:

  • (Document)

    The result of the command.



226
227
228
229
230
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 226

def find_one_and_replace(replacement, options = {})
  if doc = view.find_one_and_replace(replacement, options)
    Factory.from_db(klass, doc)
  end
end

#find_one_and_update(update, options = {}) ⇒ Document

Execute the find and modify command, used for MongoDB's $findAndModify.

Examples:

Execute the command.

context.find_one_and_update({ "$inc" => { likes: 1 }})

Parameters:

  • update (Hash)

    The updates.

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

    The command options.

Options Hash (options):

  • :return_document (:before, :after)

    Return the updated document from before or after update.

  • :upsert (true, false)

    Create the document if it doesn't exist.

Returns:

  • (Document)

    The result of the command.



206
207
208
209
210
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 206

def find_one_and_update(update, options = {})
  if doc = view.find_one_and_update(update, options)
    Factory.from_db(klass, doc)
  end
end

#first(opts = {}) ⇒ Document Also known as: one

Note:

Automatically adding a sort on _id when no other sort is defined on the criteria has the potential to cause bad performance issues. If you experience unexpected poor performance when using #first or #last and have no sort defined on the criteria, use the option { id_sort: :none }. Be aware that #first/#last won't guarantee order in this case.

Get the first document in the database for the criteria's selector.

Examples:

Get the first document.

context.first

Parameters:

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

    The options for the query returning the first document.

Options Hash (opts):

  • :id_sort (:none)

    Don't apply a sort on _id if no other sort is defined on the criteria.

Returns:



262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 262

def first(opts = {})
  return documents.first if cached? && cache_loaded?
  try_cache(:first) do
    if sort = view.sort || ({ _id: 1 } unless opts[:id_sort] == :none)
      if raw_doc = view.sort(sort).limit(1).first
        doc = Factory.from_db(klass, raw_doc, criteria)
        eager_load([doc]).first
      end
    else
      if raw_doc = view.limit(1).first
        doc = Factory.from_db(klass, raw_doc, criteria)
        eager_load([doc]).first
      end
    end
  end
end

#geo_near(coordinates) ⇒ GeoNear

Deprecated.

Execute a $geoNear command against the database.

Examples:

Find documents close to 10, 10.

context.geo_near([ 10, 10 ])

Find with spherical distance.

context.geo_near([ 10, 10 ]).spherical

Find with a max distance.

context.geo_near([ 10, 10 ]).max_distance(0.5)

Provide a distance multiplier.

context.geo_near([ 10, 10 ]).distance_multiplier(1133)

Parameters:

  • coordinates (Array<Float>)

    The coordinates.

Returns:

  • (GeoNear)

    The GeoNear command.



310
311
312
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 310

def geo_near(coordinates)
  GeoNear.new(collection, criteria, coordinates)
end

#last(opts = {}) ⇒ Object

Note:

Automatically adding a sort on _id when no other sort is defined on the criteria has the potential to cause bad performance issues. If you experience unexpected poor performance when using #first or #last and have no sort defined on the criteria, use the option { id_sort: :none }. Be aware that #first/#last won't guarantee order in this case.

Get the last document in the database for the criteria's selector.

Examples:

Get the last document.

context.last

Parameters:

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

    The options for the query returning the first document.

Options Hash (opts):

  • :id_sort (:none)

    Don't apply a sort on _id if no other sort is defined on the criteria.



369
370
371
372
373
374
375
376
377
378
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 369

def last(opts = {})
  try_cache(:last) do
    with_inverse_sorting(opts) do
      if raw_doc = view.limit(1).first
        doc = Factory.from_db(klass, raw_doc, criteria)
        eager_load([doc]).first
      end
    end
  end
end

#lengthInteger Also known as: size

Get's the number of documents matching the query selector.

Examples:

Get the length.

context.length

Returns:

  • (Integer)

    The number of documents.



386
387
388
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 386

def length
  @length ||= self.count
end

#limit(value) ⇒ Mongo

Limits the number of documents that are returned from the database.

Examples:

Limit the documents.

context.limit(20)

Parameters:

  • value (Integer)

    The number of documents to return.

Returns:

  • (Mongo)

    The context.



399
400
401
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 399

def limit(value)
  @view = view.limit(value) and self
end

#map(field = nil, &block) ⇒ Array

Invoke the block for each element of Contextual. Create a new array containing the values returned by the block.

If the symbol field name is passed instead of the block, additional optimizations would be used.

Examples:

Map by some field.

context.map(:field1)

Map with block.

context.map(&:field1)

Parameters:

  • field (Symbol) (defaults to: nil)

    The field name.

Returns:

  • (Array)

    The result of mapping.



329
330
331
332
333
334
335
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 329

def map(field = nil, &block)
  if block_given?
    super(&block)
  else
    criteria.pluck(field)
  end
end

#map_reduce(map, reduce) ⇒ MapReduce

Initiate a map/reduce operation from the context.

Examples:

Initiate a map/reduce.

context.map_reduce(map, reduce)

Parameters:

  • map (String)

    The map js function.

  • reduce (String)

    The reduce js function.

Returns:

  • (MapReduce)

    The map/reduce lazy wrapper.



412
413
414
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 412

def map_reduce(map, reduce)
  MapReduce.new(collection, criteria, map, reduce)
end

#pluck(*fields) ⇒ Array<Object, Array>

Note:

This method will return the raw db values - it performs no custom serialization.

Pluck the single field values from the database. Will return duplicates if they exist and only works for top level fields.

Examples:

Pluck a field.

context.pluck(:_id)

Parameters:

  • fields (String, Symbol, Array)

    Fields to pluck.

Returns:

  • (Array<Object, Array>)

    The plucked values.



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
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 428

def pluck(*fields)
  # Multiple fields can map to the same field name. For example, plucking
  # a field and its _translations field map to the same field in the database.
  # because of this, we need to keep track of the fields requested.
  normalized_field_names = []
  normalized_select = fields.inject({}) do |hash, f|
    db_fn = klass.database_field_name(f)
    normalized_field_names.push(db_fn)

    if Mongoid.legacy_pluck_distinct
      hash[db_fn] = true
    else
      hash[klass.cleanse_localized_field_names(f)] = true
    end
    hash
  end

  view.projection(normalized_select).reduce([]) do |plucked, doc|
    values = normalized_field_names.map do |n|
      if Mongoid.legacy_pluck_distinct
        n.include?('.') ? doc[n.partition('.')[0]] : doc[n]
      else
        extract_value(doc, n)
      end
    end
    plucked << (values.size == 1 ? values.first : values)
  end
end

#skip(value) ⇒ Mongo

Skips the provided number of documents.

Examples:

Skip the documents.

context.skip(20)

Parameters:

  • value (Integer)

    The number of documents to skip.

Returns:

  • (Mongo)

    The context.



465
466
467
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 465

def skip(value)
  @view = view.skip(value) and self
end

#sort(values = nil, &block) ⇒ Mongo

Sorts the documents by the provided spec.

Examples:

Sort the documents.

context.sort(name: -1, title: 1)

Parameters:

  • values (Hash) (defaults to: nil)

    The sorting values as field/direction(1/-1) pairs.

Returns:

  • (Mongo)

    The context.



478
479
480
481
482
483
484
485
486
487
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 478

def sort(values = nil, &block)
  if block_given?
    super(&block)
  else
    # update the criteria
    @criteria = criteria.order_by(values)
    apply_option(:sort)
    self
  end
end

#update(attributes = nil, opts = {}) ⇒ nil, false

Update the first matching document atomically.

Examples:

Update the first matching document.

context.update({ "$set" => { name: "Smiths" }})

Parameters:

  • attributes (Hash) (defaults to: nil)

    The new attributes for the document.

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

    The update operation options.

Options Hash (opts):

  • :array_filters (Array)

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

Returns:

  • (nil, false)

    False if no attributes were provided.



501
502
503
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 501

def update(attributes = nil, opts = {})
  update_documents(attributes, :update_one, opts)
end

#update_all(attributes = nil, opts = {}) ⇒ nil, false

Update all the matching documents atomically.

Examples:

Update all the matching documents.

context.update_all({ "$set" => { name: "Smiths" }})

Parameters:

  • attributes (Hash) (defaults to: nil)

    The new attributes for each document.

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

    The update operation options.

Options Hash (opts):

  • :array_filters (Array)

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

Returns:

  • (nil, false)

    False if no attributes were provided.



517
518
519
# File 'build/mongoid-master/lib/mongoid/contextual/mongo.rb', line 517

def update_all(attributes = nil, opts = {})
  update_documents(attributes, :update_many, opts)
end