Class: Mongoid::Contextual::Mongo
- Inherits:
-
Object
- Object
- Mongoid::Contextual::Mongo
- Extended by:
- Forwardable
- Includes:
- Enumerable, Association::EagerLoadable, Atomic, Aggregable::Mongo, Queryable
- Defined in:
- 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
Instance Attribute Summary collapse
-
#view ⇒ Object
readonly
Returns the value of attribute view.
- #view The Mongo collection view.(TheMongocollectionview.) ⇒ Object readonly
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
-
#cached? ⇒ true, false
Is the context cached?.
-
#count(options = {}, &block) ⇒ Integer
Get the number of documents matching the query.
-
#delete ⇒ nil
(also: #delete_all)
Delete all documents in the database that match the selector.
-
#destroy ⇒ nil
(also: #destroy_all)
Destroy all documents in the database that match the selector.
-
#distinct(field) ⇒ Array<Object>
Get the distinct values in the db for the provided field.
-
#each(&block) ⇒ Enumerator
Iterate over the context.
-
#estimated_count(options = {}) ⇒ Integer
Get the estimated number of documents matching the query.
-
#exists? ⇒ true, false
Do any documents exist for the context.
-
#explain ⇒ Hash
Run an explain on the criteria.
- #fetch_and_demongoize(d, meth, klass) ⇒ Object
-
#find_first ⇒ Object
private
Return the first result without applying sort.
-
#find_one_and_delete ⇒ Document
Execute the find and modify command, used for MongoDB’s $findAndModify.
-
#find_one_and_replace(replacement, options = {}) ⇒ Document
Execute the find and modify command, used for MongoDB’s $findAndModify.
-
#find_one_and_update(update, options = {}) ⇒ Document
Execute the find and modify command, used for MongoDB’s $findAndModify.
-
#first(limit_or_opts = nil) ⇒ Document
(also: #one)
Get the first document in the database for the criteria’s selector.
- #geo_near(coordinates) ⇒ GeoNear deprecated Deprecated.
-
#initialize(criteria) ⇒ Mongo
constructor
Create the new Mongo context.
-
#last(limit_or_opts = nil) ⇒ Document
Get the last document in the database for the criteria’s selector.
-
#length ⇒ Integer
(also: #size)
Get’s the number of documents matching the query selector.
-
#limit(value) ⇒ Mongo
Limits the number of documents that are returned from the database.
-
#map(field = nil, &block) ⇒ Array
Invoke the block for each element of Contextual.
-
#map_reduce(map, reduce) ⇒ MapReduce
Initiate a map/reduce operation from the context.
-
#pluck(*fields) ⇒ Array<Object, Array>
Pluck the single field values from the database.
-
#skip(value) ⇒ Mongo
Skips the provided number of documents.
-
#sort(values = nil, &block) ⇒ Mongo
Sorts the documents by the provided spec.
-
#take(limit = nil) ⇒ Document | Array<Document>
Take the given number of documents from the database.
-
#take! ⇒ Document
Take one document from the database and raise an error if there are none.
-
#update(attributes = nil, opts = {}) ⇒ nil, false
Update the first matching document atomically.
-
#update_all(attributes = nil, opts = {}) ⇒ nil, false
Update all the matching documents atomically.
Methods included from Queryable
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.
350 351 352 353 354 355 356 |
# File 'lib/mongoid/contextual/mongo.rb', line 350 def initialize(criteria) @criteria, @klass, @cache = criteria, criteria.klass, criteria.[:cache] @collection = @klass.collection criteria.send(:merge_type_selection) @view = collection.find(criteria.selector, session: _session) end |
Instance Attribute Details
#view ⇒ Object (readonly)
Returns the value of attribute view.
36 37 38 |
# File 'lib/mongoid/contextual/mongo.rb', line 36 def view @view end |
#view The Mongo collection view.(TheMongocollectionview.) ⇒ Object (readonly)
36 |
# File 'lib/mongoid/contextual/mongo.rb', line 36 attr_reader :view |
Instance Method Details
#cached? ⇒ true, false
Is the context cached?
44 45 46 47 |
# File 'lib/mongoid/contextual/mongo.rb', line 44 def cached? Mongoid::Warnings.warn_criteria_cache_deprecated !!@cache end |
#count(options = {}, &block) ⇒ Integer
Get the number of documents matching the query.
66 67 68 69 |
# File 'lib/mongoid/contextual/mongo.rb', line 66 def count( = {}, &block) return super(&block) if block_given? try_cache(:count) { view.count_documents() } end |
#delete ⇒ nil Also known as: delete_all
Delete all documents in the database that match the selector.
96 97 98 |
# File 'lib/mongoid/contextual/mongo.rb', line 96 def delete view.delete_many.deleted_count end |
#destroy ⇒ nil Also known as: destroy_all
Destroy all documents in the database that match the selector.
107 108 109 110 111 112 113 |
# File 'lib/mongoid/contextual/mongo.rb', line 107 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.
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/mongoid/contextual/mongo.rb', line 124 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.
150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/mongoid/contextual/mongo.rb', line 150 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.
83 84 85 86 87 88 |
# File 'lib/mongoid/contextual/mongo.rb', line 83 def estimated_count( = {}) unless self.criteria.selector.empty? raise Mongoid::Errors::InvalidEstimatedCountCriteria.new(self.klass) end try_cache(:estimated_count) { view.estimated_document_count() } end |
#exists? ⇒ true, false
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.
172 173 174 175 176 177 178 179 |
# File 'lib/mongoid/contextual/mongo.rb', line 172 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 |
#explain ⇒ Hash
Run an explain on the criteria.
187 188 189 |
# File 'lib/mongoid/contextual/mongo.rb', line 187 def explain view.explain end |
#fetch_and_demongoize(d, meth, klass) ⇒ Object
801 802 803 804 805 806 807 808 |
# File 'lib/mongoid/contextual/mongo.rb', line 801 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_first ⇒ Object
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
285 286 287 288 289 290 291 |
# File 'lib/mongoid/contextual/mongo.rb', line 285 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_delete ⇒ Document
Execute the find and modify command, used for MongoDB’s $findAndModify. This deletes the found document.
238 239 240 241 242 |
# File 'lib/mongoid/contextual/mongo.rb', line 238 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.
225 226 227 228 229 |
# File 'lib/mongoid/contextual/mongo.rb', line 225 def find_one_and_replace(replacement, = {}) if doc = view.find_one_and_replace(replacement, ) 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.
205 206 207 208 209 |
# File 'lib/mongoid/contextual/mongo.rb', line 205 def find_one_and_update(update, = {}) if doc = view.find_one_and_update(update, ) Factory.from_db(klass, doc) end end |
#first(limit_or_opts = nil) ⇒ Document Also known as: one
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.
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/mongoid/contextual/mongo.rb', line 262 def first(limit_or_opts = nil) limit, opts = extract_limit_and_opts(limit_or_opts) if cached? && cache_loaded? return limit ? documents.first(limit) : documents.first end try_numbered_cache(:first, limit) do if opts.key?(:id_sort) Mongoid::Warnings.warn_id_sort_deprecated end sorted_view = view if sort = view.sort || ({ _id: 1 } unless opts[:id_sort] == :none) sorted_view = view.sort(sort) end if raw_docs = sorted_view.limit(limit || 1).to_a process_raw_docs(raw_docs, limit) end end end |
#geo_near(coordinates) ⇒ GeoNear
Execute a $geoNear command against the database.
312 313 314 |
# File 'lib/mongoid/contextual/mongo.rb', line 312 def geo_near(coordinates) GeoNear.new(collection, criteria, coordinates) end |
#last(limit_or_opts = nil) ⇒ Document
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.
378 379 380 381 382 383 384 385 386 387 388 389 390 391 |
# File 'lib/mongoid/contextual/mongo.rb', line 378 def last(limit_or_opts = nil) limit, opts = extract_limit_and_opts(limit_or_opts) if cached? && cache_loaded? return limit ? documents.last(limit) : documents.last end res = try_numbered_cache(:last, limit) do with_inverse_sorting(opts) do if raw_docs = view.limit(limit || 1).to_a process_raw_docs(raw_docs, limit) end end end res.is_a?(Array) ? res.reverse : res end |
#length ⇒ Integer Also known as: size
Get’s the number of documents matching the query selector.
399 400 401 |
# File 'lib/mongoid/contextual/mongo.rb', line 399 def length @length ||= self.count end |
#limit(value) ⇒ Mongo
Limits the number of documents that are returned from the database.
412 413 414 |
# File 'lib/mongoid/contextual/mongo.rb', line 412 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.
331 332 333 334 335 336 337 338 339 340 341 |
# File 'lib/mongoid/contextual/mongo.rb', line 331 def map(field = nil, &block) if !field.nil? Mongoid::Warnings.warn_map_field_deprecated end if block_given? super(&block) else criteria.pluck(field) end end |
#map_reduce(map, reduce) ⇒ MapReduce
Initiate a map/reduce operation from the context.
463 464 465 |
# File 'lib/mongoid/contextual/mongo.rb', line 463 def map_reduce(map, reduce) MapReduce.new(collection, criteria, map, reduce) end |
#pluck(*fields) ⇒ Array<Object, Array>
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.
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 |
# File 'lib/mongoid/contextual/mongo.rb', line 479 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.
516 517 518 |
# File 'lib/mongoid/contextual/mongo.rb', line 516 def skip(value) @view = view.skip(value) and self end |
#sort(values = nil, &block) ⇒ Mongo
Sorts the documents by the provided spec.
529 530 531 532 533 534 535 536 537 538 |
# File 'lib/mongoid/contextual/mongo.rb', line 529 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 |
#take(limit = nil) ⇒ Document | Array<Document>
Take the given number of documents from the database.
425 426 427 428 429 430 431 432 433 |
# File 'lib/mongoid/contextual/mongo.rb', line 425 def take(limit = nil) if limit limit(limit).to_a else # Do to_a first so that the Mongo#first method is not used and the # result is not sorted. limit(1).to_a.first end end |
#take! ⇒ Document
Take one document from the database and raise an error if there are none.
444 445 446 447 448 449 450 451 452 |
# File 'lib/mongoid/contextual/mongo.rb', line 444 def take! # Do to_a first so that the Mongo#first method is not used and the # result is not sorted. if fst = limit(1).to_a.first fst else raise Errors::DocumentNotFound.new(klass, nil, nil) end end |
#update(attributes = nil, opts = {}) ⇒ nil, false
Update the first matching document atomically.
552 553 554 |
# File 'lib/mongoid/contextual/mongo.rb', line 552 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.
568 569 570 |
# File 'lib/mongoid/contextual/mongo.rb', line 568 def update_all(attributes = nil, opts = {}) update_documents(attributes, :update_many, opts) end |