Class: Mongoid::Contextual::Mongo
- Inherits:
-
Object
- Object
- Mongoid::Contextual::Mongo
- Extended by:
- Forwardable
- Includes:
- Enumerable, Association::EagerLoadable, Atomic, Aggregable::Mongo, Queryable
- Defined in:
- build/mongoid-8.0/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
-
#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.
-
#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 = 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 = nil) ⇒ Document
Get the last document in the database for the criteria’s selector.
-
#length ⇒ Integer
(also: #size)
Returns the number of documents in the database matching the query selector.
-
#limit(value) ⇒ Mongo
Limits the number of documents that are returned from the database.
-
#map_reduce(map, reduce) ⇒ MapReduce
Initiate a map/reduce operation from the context.
-
#pick(*fields) ⇒ Object | Array<Object>
Pick the single field values from the database.
-
#pluck(*fields) ⇒ Array<Object> | Array<Array<Object>>
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.
-
#tally(field) ⇒ Hash
Get a hash of counts for the values of a single field.
-
#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.
290 291 292 293 294 295 296 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 290 def initialize(criteria) @criteria, @klass = criteria, criteria.klass @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.
38 39 40 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 38 def view @view end |
#view The Mongo collection view.(TheMongocollectionview.) ⇒ Object (readonly)
38 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 38 attr_reader :view |
Instance Method Details
#count(options = {}, &block) ⇒ Integer
Get the number of documents matching the query.
57 58 59 60 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 57 def count( = {}, &block) return super(&block) if block_given? view.count_documents() end |
#delete ⇒ nil Also known as: delete_all
Delete all documents in the database that match the selector.
87 88 89 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 87 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.
98 99 100 101 102 103 104 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 98 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.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 115 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.
141 142 143 144 145 146 147 148 149 150 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 141 def each(&block) if block_given? documents_for_iteration.each do |doc| yield_document(doc, &block) end 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.
74 75 76 77 78 79 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 74 def estimated_count( = {}) unless self.criteria.selector.empty? raise Mongoid::Errors::InvalidEstimatedCountCriteria.new(self.klass) end view.estimated_document_count() end |
#exists? ⇒ true | false
We don’t use count here since Mongo does not use counted b-tree indexes.
Do any documents exist for the context.
161 162 163 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 161 def exists? !!(view.projection(_id: 1).limit(1).first) end |
#explain ⇒ Hash
Run an explain on the criteria.
171 172 173 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 171 def explain view.explain 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
253 254 255 256 257 258 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 253 def find_first 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.
222 223 224 225 226 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 222 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.
209 210 211 212 213 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 209 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.
189 190 191 192 193 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 189 def find_one_and_update(update, = {}) if doc = view.find_one_and_update(update, ) Factory.from_db(klass, doc) end end |
#first(limit = 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 #take instead. Be aware that #take won’t guarantee order.
Get the first document in the database for the criteria’s selector.
242 243 244 245 246 247 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 242 def first(limit = nil) sort = view.sort || { _id: 1 } if raw_docs = view.sort(sort).limit(limit || 1).to_a process_raw_docs(raw_docs, limit) end end |
#geo_near(coordinates) ⇒ GeoNear
Execute a $geoNear command against the database.
279 280 281 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 279 def geo_near(coordinates) GeoNear.new(collection, criteria, coordinates) end |
#last(limit = 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 #take instead. Be aware that #take won’t guarantee order.
Get the last document in the database for the criteria’s selector.
314 315 316 317 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 314 def last(limit = nil) raw_docs = view.sort(inverse_sorting).limit(limit || 1).to_a.reverse process_raw_docs(raw_docs, limit) end |
#length ⇒ Integer Also known as: size
Returns the number of documents in the database matching the query selector.
326 327 328 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 326 def length self.count end |
#limit(value) ⇒ Mongo
Limits the number of documents that are returned from the database.
339 340 341 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 339 def limit(value) @view = view.limit(value) and self end |
#map_reduce(map, reduce) ⇒ MapReduce
Initiate a map/reduce operation from the context.
390 391 392 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 390 def map_reduce(map, reduce) MapReduce.new(collection, criteria, map, reduce) end |
#pick(*fields) ⇒ Object | Array<Object>
Pick the single field values from the database.
440 441 442 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 440 def pick(*fields) limit(1).pluck(*fields).first end |
#pluck(*fields) ⇒ Array<Object> | Array<Array<Object>>
Pluck the single field values from the database. Will return duplicates if they exist and only works for top level fields.
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 403 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.
521 522 523 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 521 def skip(value) @view = view.skip(value) and self end |
#sort(values = nil, &block) ⇒ Mongo
Sorts the documents by the provided spec.
534 535 536 537 538 539 540 541 542 543 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 534 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.
352 353 354 355 356 357 358 359 360 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 352 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.
371 372 373 374 375 376 377 378 379 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 371 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 |
#tally(field) ⇒ Hash
Get a hash of counts for the values of a single field. For example, if the following documents were in the database:
{ _id: 1, age: 21 }
{ _id: 2, age: 21 }
{ _id: 3, age: 22 }
Model.tally("age")
would yield the following result:
{ 21 => 2, 22 => 1 }
When tallying a field inside an array or embeds_many association:
{ _id: 1, array: [ { x: 1 }, { x: 2 } ] }
{ _id: 2, array: [ { x: 1 }, { x: 2 } ] }
{ _id: 3, array: [ { x: 1 }, { x: 3 } ] }
Model.tally("array.x")
The keys of the resulting hash are arrays:
{ [ 1, 2 ] => 2, [ 1, 3 ] => 1 }
Note that if tallying an element in an array of hashes, and the key doesn’t exist in some of the hashes, tally will not include those nil keys in the resulting hash:
{ _id: 1, array: [ { x: 1 }, { x: 2 }, { y: 3 } ] }
Model.tally("array.x")
# => { [ 1, 2 ] => 1 }
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 507 508 509 510 511 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 481 def tally(field) name = klass.cleanse_localized_field_names(field) fld = klass.traverse_association_tree(name) pipeline = [ { "$group" => { _id: "$#{name}", counts: { "$sum": 1 } } } ] pipeline.unshift("$match" => view.filter) unless view.filter.blank? collection.aggregate(pipeline).reduce({}) do |tallies, doc| is_translation = "#{name}_translations" == field.to_s val = doc["_id"] key = if val.is_a?(Array) val.map do |v| demongoize_with_field(fld, v, is_translation) end else demongoize_with_field(fld, val, is_translation) end # The only time where a key will already exist in the tallies hash # is when the values are stored differently in the database, but # demongoize to the same value. A good example of when this happens # is when using localized fields. While the server query won't group # together hashes that have other values in different languages, the # demongoized value is just the translation in the current locale, # which can be the same across multiple of those unequal hashes. tallies[key] ||= 0 tallies[key] += doc["counts"] tallies end end |
#update(attributes = nil, opts = {}) ⇒ nil, false
Update the first matching document atomically.
557 558 559 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 557 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.
573 574 575 |
# File 'build/mongoid-8.0/lib/mongoid/contextual/mongo.rb', line 573 def update_all(attributes = nil, opts = {}) update_documents(attributes, :update_many, opts) end |