Class: Mongoid::Contextual::Mongo
Relationships & Source Files | |
Namespace Children | |
Classes:
| |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
Forwardable
|
|
Instance Chain:
self,
Queryable ,
::Mongoid::Association::EagerLoadable ,
::Mongoid::Atomic ,
Aggregable::Mongo ,
Enumerable
|
|
Inherits: | Object |
Defined in: | lib/mongoid/contextual/mongo.rb, lib/mongoid/contextual/mongo/documents_loader.rb |
Overview
Context object used for performing bulk query and persistence operations on documents which are persisted in the database and have not been loaded into application memory.
Constant Summary
-
OPTIONS =
Options constant.
[ :hint, :limit, :skip, :sort, :batch_size, :max_scan, :max_time_ms, :snapshot, :comment, :read, :cursor_type, :collation ].freeze
::Mongoid::Atomic
- Included
::Mongoid::Atomic
- Attributes & Methods
Class Method Summary
-
.new(criteria) ⇒ Mongo
constructor
Create the new
Mongo
context.
Instance Attribute Summary
- #documents_loader readonly
-
#view ⇒ Hash
readonly
Run an explain on the criteria.
- #view The Mongo collection view.(The Mongo collection view.) readonly
- #acknowledged_write? ⇒ Boolean readonly private
Queryable
- Included
#blank? | Is the enumerable of matching documents empty? |
#collection, #collection The collection to query against., #criteria, #criteria The criteria for the context., | |
#empty? | Alias for Queryable#blank?. |
#klass, #klass The klass for the criteria. |
::Mongoid::Association::EagerLoadable
- Included
#eager_loadable? | Indicates whether the criteria has association inclusions which should be eager loaded. |
Instance Method Summary
-
#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.
-
#delete_all
Alias for #delete.
-
#destroy ⇒ nil
(also: #destroy_all)
Destroy all documents in the database that match the selector.
-
#destroy_all
Alias for #destroy.
-
#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?(id_or_conditions = :none) ⇒ true | false
Do any documents exist for the context.
-
#fifth ⇒ Document | nil
Get the fifth document in the database for the criteria’s selector.
-
#fifth! ⇒ Document
Get the fifth document in the database for the criteria’s selector or raise an error if none is found.
-
#find_first
Internal use only
Internal use only
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 | nil
(also: #one)
Get the first document in the database for the criteria’s selector.
-
#first! ⇒ Document
Get the first document in the database for the criteria’s selector or raise an error if none is found.
-
#fourth ⇒ Document | nil
Get the fourth document in the database for the criteria’s selector.
-
#fourth! ⇒ Document
Get the fourth document in the database for the criteria’s selector or raise an error if none is found.
-
#last(limit = nil) ⇒ Document | nil
Get the last document in the database for the criteria’s selector.
-
#last! ⇒ Document
Get the last document in the database for the criteria’s selector or raise an error if none is found.
-
#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.
-
#load_async
Internal use only
Internal use only
Schedule a task to load documents for the context.
-
#map_reduce(map, reduce) ⇒ MapReduce
Initiate a map/reduce operation from the context.
-
#one(limit = nil)
Alias for #first.
-
#pick(*fields) ⇒ Object | Array<Object>
Pick the single field values from the database.
-
#pluck(*fields) ⇒ Array<Object> | Array<Array<Object>>
Pluck the field value(s) from the database.
-
#second ⇒ Document | nil
Get the second document in the database for the criteria’s selector.
-
#second! ⇒ Document
Get the second document in the database for the criteria’s selector or raise an error if none is found.
-
#second_to_last ⇒ Document | nil
Get the second to last document in the database for the criteria’s selector.
-
#second_to_last! ⇒ Document
Get the second to last document in the database for the criteria’s selector or raise an error if none is found.
-
#size
Alias for #length.
-
#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.
-
#third ⇒ Document | nil
Get the third document in the database for the criteria’s selector.
-
#third! ⇒ Document
Get the third document in the database for the criteria’s selector or raise an error if none is found.
-
#third_to_last ⇒ Document | nil
Get the third to last document in the database for the criteria’s selector.
-
#third_to_last! ⇒ Document
Get the third to last document in the database for the criteria’s selector or raise an error if none is found.
-
#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.
- #_session private
-
#apply_fields
private
Internal use only
Internal use only
Apply the field limitations.
-
#apply_option(name)
private
Internal use only
Internal use only
Apply an option.
-
#apply_options
private
Internal use only
Internal use only
Apply the options.
-
#demongoize_hash(klass, hash) ⇒ Hash | nil
private
Internal use only
Internal use only
Demongoizes (converts from database to Ruby representation) the values of the given hash as if it were the raw representation of a document of the given klass.
-
#demongoize_with_field(field, value, is_translation) ⇒ Object
private
Internal use only
Internal use only
Demongoize the value for the given field.
-
#documents_for_iteration ⇒ Array<Document> | Mongo::Collection::View
private
Internal use only
Internal use only
Get the documents the context should iterate.
-
#extract_value(attrs, field_name)
private
Extracts the value for the given field name from the given attribute hash.
-
#fetch_and_demongoize(obj, meth, field) ⇒ Object
private
Internal use only
Internal use only
Fetch the element from the given hash and demongoize it using the given field.
-
#inverse_sorting
private
Internal use only
Internal use only
Map the inverse sort symbols to the correct MongoDB values.
-
#process_raw_docs(raw_docs, limit) ⇒ Array<Document> | Document
private
Process the raw documents retrieved for #first/#last.
- #raise_document_not_found_error private
-
#recursive_demongoize(field_name, value, is_translation) ⇒ Object
private
Recursively demongoize the given value.
- #retrieve_nth(n) private
- #retrieve_nth_to_last(n) private
- #retrieve_nth_to_last_with_limit(n, limit) private
- #retrieve_nth_with_limit(n, limit) private
-
#update_documents(attributes, method = :update_one, opts = {}) ⇒ true | false
private
Internal use only
Internal use only
Update the documents for the provided method.
-
#valid_for_count_documents?(hash = view.filter) ⇒ true | false
private
Queries whether the current context is valid for use with the #count_documents? predicate.
-
#yield_document(document) {|doc| ... }
private
Internal use only
Internal use only
Yield to the document.
::Mongoid::Association::EagerLoadable
- Included
#eager_load | Load the associations for the given documents. |
#preload | Load the associations for the given documents. |
::Mongoid::Atomic
- Included
#_updates | Alias for Atomic#atomic_updates. |
#add_atomic_pull | Add the document as an atomic pull. |
#add_atomic_unset | Add an atomic unset for the document. |
#atomic_array_add_to_sets | For array fields these are the unique adds that need to happen. |
#atomic_array_pulls | For array fields these are the pulls that need to happen. |
#atomic_array_pushes | For array fields these are the pushes that need to happen. |
#atomic_attribute_name | Returns path of the attribute for modification. |
#atomic_delete_modifier | Get the removal modifier for the document. |
#atomic_insert_modifier | Get the insertion modifier for the document. |
#atomic_path | Return the path to this |
#atomic_paths | Get the atomic paths utility for this document. |
#atomic_position | Returns the positional operator of this document for modification. |
#atomic_pulls | Get all the attributes that need to be pulled. |
#atomic_pushes | Get all the push attributes that need to occur. |
#atomic_sets | Get all the attributes that need to be set. |
#atomic_unsets | Get all the attributes that need to be unset. |
#atomic_updates | Get all the atomic updates that need to happen for the current |
#delayed_atomic_pulls | Get a hash of atomic pulls that are pending. |
#delayed_atomic_sets | Get all the atomic sets that have had their saves delayed. |
#delayed_atomic_unsets | Get the delayed atomic unsets. |
#flag_as_destroyed | Flag the document as destroyed and return the atomic path. |
#flagged_destroys | Get the flagged destroys. |
#process_flagged_destroys | Process all the pending flagged destroys from nested attributes. |
#generate_atomic_updates | Generates the atomic updates in the correct order. |
#reset_atomic_updates! | Clears all pending atomic updates. |
Aggregable::Mongo
- Included
#aggregates | Get all the aggregate values for the provided field. |
#avg | Get the average value of the provided field. |
#max | Get the max value of the provided field. |
#min | Get the min value of the provided field. |
#sum | Get the sum value of the provided field. |
#pipeline | Get the aggregation pipeline for provided field. |
Constructor Details
.new(criteria) ⇒ Mongo
Create the new Mongo
context. This delegates operations to the underlying driver.
# File 'lib/mongoid/contextual/mongo.rb', line 270
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
#_index (rw)
When MongoDB finally fully implements the positional operator, we can get rid of all indexing related code in ::Mongoid
.
# File 'lib/mongoid/atomic.rb', line 25
attr_accessor :_index
#acknowledged_write? ⇒ Boolean (readonly, private)
[ GitHub ]# File 'lib/mongoid/contextual/mongo.rb', line 902
def acknowledged_write? collection.write_concern.nil? || collection.write_concern.acknowledged? end
#documents_loader (readonly)
[ GitHub ]# File 'lib/mongoid/contextual/mongo.rb', line 54
attr_reader :documents_loader
#view ⇒ Hash (readonly)
Run an explain on the criteria.
# File 'lib/mongoid/contextual/mongo.rb', line 42
attr_reader :view
#view The Mongo collection view.(The Mongo collection view.) (readonly)
[ GitHub ]# File 'lib/mongoid/contextual/mongo.rb', line 42
attr_reader :view
Instance Method Details
#_session (private)
[ GitHub ]# File 'lib/mongoid/contextual/mongo.rb', line 898
def _session @criteria.send(:_session) end
#apply_fields (private)
Apply the field limitations.
# File 'lib/mongoid/contextual/mongo.rb', line 805
def apply_fields if spec = criteria. [:fields] @view = view.projection(spec) end end
#apply_option(name) (private)
Apply an option.
# File 'lib/mongoid/contextual/mongo.rb', line 833
def apply_option(name) if spec = criteria. [name] @view = view.send(name, spec) end end
#apply_options (private)
Apply the options.
# File 'lib/mongoid/contextual/mongo.rb', line 817
def apply_fields OPTIONS.each do |name| apply_option(name) end if criteria. [:timeout] == false @view = view.no_cursor_timeout end end
#count(options = {}, &block) ⇒ Integer
Get the number of documents matching the query.
# File 'lib/mongoid/contextual/mongo.rb', line 73
def count( = {}, &block) return super(&block) if block_given? if valid_for_count_documents? view.count_documents( ) else # TODO: Remove this when we remove the deprecated for_js API. # https://jira.mongodb.org/browse/MONGOID-5681 view.count( ) end end
#delete ⇒ nil
Also known as: #delete_all
Delete all documents in the database that match the selector.
# File 'lib/mongoid/contextual/mongo.rb', line 114
def delete view.delete_many.deleted_count end
#delete_all
Alias for #delete.
# File 'lib/mongoid/contextual/mongo.rb', line 117
alias :delete_all :delete
#demongoize_hash(klass, hash) ⇒ Hash | nil
(private)
this method will modify the given hash, in-place, for performance
Demongoizes (converts from database to Ruby representation) the values of the given hash as if it were the raw representation of a document of the given klass.
reasons. If you wish to preserve the original hash, duplicate it before passing it to this method.
# File 'lib/mongoid/contextual/mongo.rb', line 1009
def demongoize_hash(klass, hash) return nil unless hash hash.each_key do |key| value = hash[key] # does the key represent a declared field on the document? if (field = klass.fields[key]) hash[key] = field.demongoize(value) next end # does the key represent an emebedded relation on the document? aliased_name = klass.aliased_associations[key] || key if (assoc = klass.relations[aliased_name]) case value when Array then value.each { |h| demongoize_hash(assoc.klass, h) } when Hash then demongoize_hash(assoc.klass, value) end end end hash end
#demongoize_with_field(field, value, is_translation) ⇒ Object
(private)
Demongoize the value for the given field. If the field is nil or the field is a translations field, the value is demongoized using its class.
# File 'lib/mongoid/contextual/mongo.rb', line 1045
def demongoize_with_field(field, value, is_translation) if field # If it's a localized field that's not a hash, don't demongoize # again, we already have the translation. If it's an _translations # field, don't demongoize, we want the full hash not just a # specific translation. # If it is a hash, and it's not a translations field, we need to # demongoize to get the correct translation. if field.localized? && (!value.is_a?(Hash) || is_translation) value.class.demongoize(value) else field.demongoize(value) end else value.class.demongoize(value) end end
#destroy ⇒ nil
Also known as: #destroy_all
Destroy all documents in the database that match the selector.
# File 'lib/mongoid/contextual/mongo.rb', line 125
def destroy each.inject(0) do |count, doc| doc.destroy count += 1 if acknowledged_write? count end end
#destroy_all
Alias for #destroy.
# File 'lib/mongoid/contextual/mongo.rb', line 132
alias :destroy_all :destroy
#distinct(field) ⇒ Array<Object
>
Get the distinct values in the db for the provided field.
# File 'lib/mongoid/contextual/mongo.rb', line 142
def distinct(field) name = klass.cleanse_localized_field_names(field) view.distinct(name).map do |value| is_translation = "#{name}_translations" == field.to_s recursive_demongoize(name, value, is_translation) end end
#documents_for_iteration ⇒ Array<Document> | Mongo::Collection::View
(private)
Get the documents the context should iterate.
If the documents have been already preloaded by Document::Loader
instance, they will be used.
# File 'lib/mongoid/contextual/mongo.rb', line 855
def documents_for_iteration if @documents_loader if @documents_loader.started? @documents_loader.value! else @documents_loader.unschedule @documents_loader.execute end else return view unless eager_loadable? docs = view.map do |doc| Factory.from_db(klass, doc, criteria) end eager_load(docs) end end
#each(&block) ⇒ Enumerator
Iterate over the context. If provided a block, yield to a ::Mongoid
document for each, otherwise return an enum.
# File 'lib/mongoid/contextual/mongo.rb', line 160
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.
# File 'lib/mongoid/contextual/mongo.rb', line 97
def estimated_count( = {}) unless self.criteria.selector.empty? if klass.default_scoping? raise Mongoid::Errors::InvalidEstimatedCountScoping.new(self.klass) else raise Mongoid::Errors::InvalidEstimatedCountCriteria.new(self.klass) end end view.estimated_document_count( ) end
#exists?(id_or_conditions = :none) ⇒ true
| false
We don’t use count here since Mongo
does not use counted b-tree indexes.
Do any documents exist for the context.
# File 'lib/mongoid/contextual/mongo.rb', line 190
def exists?(id_or_conditions = :none) return false if self.view.limit == 0 case id_or_conditions when :none then !!(view.projection(_id: 1).limit(1).first) when nil, false then false when Hash then Mongo.new(criteria.where(id_or_conditions)).exists? else Mongo.new(criteria.where(_id: id_or_conditions)).exists? end end
#extract_value(attrs, field_name) (private)
Extracts the value for the given field name from the given attribute hash.
# File 'lib/mongoid/contextual/mongo.rb', line 933
def extract_value(attrs, field_name) i = 1 num_meths = field_name.count('.') + 1 curr = attrs.dup klass.traverse_association_tree(field_name) do |meth, obj, is_field| field = obj if is_field is_translation = false # If no association or field was found, check if the meth is an # _translations field. if obj.nil? & tr = meth.match(/(.*)_translations\z/)&.captures&.first is_translation = true meth = tr end # 1. If curr is an array fetch from all elements in the array. # 2. If the field is localized, and is not an _translations field # (_translations fields don't show up in the fields hash). # - If this is the end of the methods, return the translation for # the current locale. # - Otherwise, return the whole translations hash so the next method # can select the language it wants. # 3. If the meth is an _translations field, do not demongoize the # value so the full hash is returned. # 4. Otherwise, fetch and demongoize the value for the key meth. curr = if curr.is_a? Array res = fetch_and_demongoize(curr, meth, field) res.empty? ? nil : res elsif !is_translation && field&.localized? if i < num_meths curr.try(:fetch, meth, nil) else fetch_and_demongoize(curr, meth, field) end elsif is_translation curr.try(:fetch, meth, nil) else fetch_and_demongoize(curr, meth, field) end i += 1 end curr end
#fetch_and_demongoize(obj, meth, field) ⇒ Object
(private)
Fetch the element from the given hash and demongoize it using the given field. If the obj is an array, map over it and call this method on all of its elements.
# File 'lib/mongoid/contextual/mongo.rb', line 917
def fetch_and_demongoize(obj, meth, field) if obj.is_a?(Array) obj.map { |doc| fetch_and_demongoize(doc, meth, field) } else res = obj.try(:fetch, meth, nil) field ? field.demongoize(res) : res.class.demongoize(res) end end
#fifth ⇒ Document | nil
Get the fifth document in the database for the criteria’s selector.
# File 'lib/mongoid/contextual/mongo.rb', line 699
def fifth retrieve_nth(4) end
#fifth! ⇒ Document
Get the fifth document in the database for the criteria’s selector or raise an error if none is found.
# File 'lib/mongoid/contextual/mongo.rb', line 713
def fifth! fifth || raise_document_not_found_error end
#find_first
Return the first result without applying sort
#find_one_and_delete ⇒ Document
Execute the find and modify command, used for MongoDB’s $findAndModify. This deletes the found document.
#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 | nil
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.
# File 'lib/mongoid/contextual/mongo.rb', line 550
def first(limit = nil) if limit.nil? retrieve_nth(0) else retrieve_nth_with_limit(0, limit) end end
#first! ⇒ 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 first document in the database for the criteria’s selector or raise an error if none is found.
# File 'lib/mongoid/contextual/mongo.rb', line 575
def first! first || raise_document_not_found_error end
#fourth ⇒ Document | nil
Get the fourth document in the database for the criteria’s selector.
# File 'lib/mongoid/contextual/mongo.rb', line 675
def fourth retrieve_nth(3) end
#fourth! ⇒ Document
Get the fourth document in the database for the criteria’s selector or raise an error if none is found.
# File 'lib/mongoid/contextual/mongo.rb', line 689
def fourth! fourth || raise_document_not_found_error end
#inverse_sorting (private)
Map the inverse sort symbols to the correct MongoDB values.
#last(limit = nil) ⇒ Document | nil
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.
# File 'lib/mongoid/contextual/mongo.rb', line 593
def last(limit = nil) if limit.nil? retrieve_nth_to_last(0) else retrieve_nth_to_last_with_limit(0, limit) end end
#last! ⇒ 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 or raise an error if none is found.
# File 'lib/mongoid/contextual/mongo.rb', line 617
def last! last || raise_document_not_found_error end
#length ⇒ Integer Also known as: #size
Returns the number of documents in the database matching the query selector.
# File 'lib/mongoid/contextual/mongo.rb', line 287
def length self.count end
#limit(value) ⇒ Mongo
Limits the number of documents that are returned from the database.
# File 'lib/mongoid/contextual/mongo.rb', line 300
def limit(value) @view = view.limit(value) and self end
#load_async
Schedule a task to load documents for the context.
Depending on the ::Mongoid
configuration, the scheduled task can be executed immediately on the caller’s thread, or can be scheduled for an asynchronous execution.
# File 'lib/mongoid/contextual/mongo.rb', line 776
def load_async @documents_loader ||= DocumentsLoader.new(view, klass, criteria) end
#map_reduce(map, reduce) ⇒ MapReduce
Initiate a map/reduce operation from the context.
#one(limit = nil)
Alias for #first.
# File 'lib/mongoid/contextual/mongo.rb', line 557
alias :one :first
#pick(*fields) ⇒ Object
| Array<Object
>
Pick the single field values from the database.
#pluck(*fields) ⇒ Array<Object
> | Array<Array<Object
>>
Pluck the field value(s) from the database. Returns one result for each document found in the database for the context. The results are normalized according to their ::Mongoid
field types. Note that the results may include duplicates and nil values.
# File 'lib/mongoid/contextual/mongo.rb', line 333
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) hash[klass.cleanse_localized_field_names(f)] = true hash end view.projection(normalized_select).reduce([]) do |plucked, doc| values = normalized_field_names.map do |n| extract_value(doc, n) end plucked << (values.size == 1 ? values.first : values) end end
#process_raw_docs(raw_docs, limit) ⇒ Array<Document> | Document (private)
Process the raw documents retrieved for #first/#last.
# File 'lib/mongoid/contextual/mongo.rb', line 1067
def process_raw_docs(raw_docs, limit) docs = if criteria.raw_results? if criteria.typecast_results? raw_docs.map { |doc| demongoize_hash(klass, doc) } else raw_docs end else mapped = raw_docs.map { |doc| Factory.from_db(klass, doc, criteria) } eager_load(mapped) end limit ? docs : docs.first end
#raise_document_not_found_error (private)
# File 'lib/mongoid/contextual/mongo.rb', line 1103
def raise_document_not_found_error raise Errors::DocumentNotFound.new(klass, nil, nil) end
#recursive_demongoize(field_name, value, is_translation) ⇒ Object
(private)
Recursively demongoize the given value. This method recursively traverses the class tree to find the correct field to use to demongoize the value.
# File 'lib/mongoid/contextual/mongo.rb', line 987
def recursive_demongoize(field_name, value, is_translation) field = klass.traverse_association_tree(field_name) demongoize_with_field(field, value, is_translation) end
#retrieve_nth(n) (private)
[ GitHub ]# File 'lib/mongoid/contextual/mongo.rb', line 1107
def retrieve_nth(n) retrieve_nth_with_limit(n, 1).first end
#retrieve_nth_to_last(n) (private)
[ GitHub ]# File 'lib/mongoid/contextual/mongo.rb', line 1120
def retrieve_nth_to_last(n) retrieve_nth_to_last_with_limit(n, 1).first end
#retrieve_nth_to_last_with_limit(n, limit) (private)
[ GitHub ]# File 'lib/mongoid/contextual/mongo.rb', line 1124
def retrieve_nth_to_last_with_limit(n, limit) v = view.sort(inverse_sorting).skip(n).limit(limit || 1) v = v.skip(n) if n > 0 raw_docs = v.to_a.reverse process_raw_docs(raw_docs, limit) end
#retrieve_nth_with_limit(n, limit) (private)
[ GitHub ]
#second ⇒ Document | nil
Get the second document in the database for the criteria’s selector.
# File 'lib/mongoid/contextual/mongo.rb', line 627
def second retrieve_nth(1) end
#second! ⇒ Document
Get the second document in the database for the criteria’s selector or raise an error if none is found.
# File 'lib/mongoid/contextual/mongo.rb', line 641
def second! second || raise_document_not_found_error end
#second_to_last ⇒ Document | nil
Get the second to last document in the database for the criteria’s selector.
is found.
# File 'lib/mongoid/contextual/mongo.rb', line 725
def second_to_last retrieve_nth_to_last(1) end
#second_to_last! ⇒ Document
Get the second to last document in the database for the criteria’s selector or raise an error if none is found.
# File 'lib/mongoid/contextual/mongo.rb', line 739
def second_to_last! second_to_last || raise_document_not_found_error end
#size
Alias for #length.
# File 'lib/mongoid/contextual/mongo.rb', line 290
alias :size :length
#skip(value) ⇒ Mongo
Skips the provided number of documents.
# File 'lib/mongoid/contextual/mongo.rb', line 480
def skip(value) @view = view.skip(value) and self end
#sort(values = nil, &block) ⇒ Mongo
Sorts the documents by the provided spec.
# File 'lib/mongoid/contextual/mongo.rb', line 493
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.
#take! ⇒ Document
Take one document from the database and raise an error if there are none.
# File 'lib/mongoid/contextual/mongo.rb', line 393
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 }
# File 'lib/mongoid/contextual/mongo.rb', line 440
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
#third ⇒ Document | nil
Get the third document in the database for the criteria’s selector.
# File 'lib/mongoid/contextual/mongo.rb', line 651
def third retrieve_nth(2) end
#third! ⇒ Document
Get the third document in the database for the criteria’s selector or raise an error if none is found.
# File 'lib/mongoid/contextual/mongo.rb', line 665
def third! third || raise_document_not_found_error end
#third_to_last ⇒ Document | nil
Get the third to last document in the database for the criteria’s selector.
is found.
# File 'lib/mongoid/contextual/mongo.rb', line 751
def third_to_last retrieve_nth_to_last(2) end
#third_to_last! ⇒ Document
Get the third to last document in the database for the criteria’s selector or raise an error if none is found.
# File 'lib/mongoid/contextual/mongo.rb', line 765
def third_to_last! third_to_last || raise_document_not_found_error end
#update(attributes = nil, opts = {}) ⇒ nil
| false
Update the first matching document atomically.
# File 'lib/mongoid/contextual/mongo.rb', line 516
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.
# File 'lib/mongoid/contextual/mongo.rb', line 532
def update_all(attributes = nil, opts = {}) update_documents(attributes, :update_many, opts) end
#update_documents(attributes, method = :update_one, opts = {}) ⇒ true
| false
(private)
Update the documents for the provided method.
# File 'lib/mongoid/contextual/mongo.rb', line 793
def update_documents(attributes, method = :update_one, opts = {}) return false unless attributes view.send(method, AtomicUpdatePreparer.prepare(attributes, klass), opts) end
#valid_for_count_documents?(hash = view.filter) ⇒ true
| false
(private)
Queries whether the current context is valid for use with the #count_documents? predicate. A context is valid if it does not include a $where
operator.
TODO: Remove this method when we remove the deprecated for_js API. jira.mongodb.org/browse/MONGOID-5681
# File 'lib/mongoid/contextual/mongo.rb', line 1091
def valid_for_count_documents?(hash = view.filter) # Note that `view.filter` is a BSON::Document, and all keys in a # BSON::Document are strings; we don't need to worry about symbol # representations of `$where`. hash.keys.each do |key| return false if key == '$where' return false if hash[key].is_a?(Hash) && !valid_for_count_documents?(hash[key]) end true end
#yield_document(document) {|doc| ... } (private)
Yield to the document.
# File 'lib/mongoid/contextual/mongo.rb', line 882
def yield_document(document, &block) doc = if document.respond_to?(:_id) document elsif criteria.raw_results? if criteria.typecast_results? demongoize_hash(klass, document) else document end else Factory.from_db(klass, document, criteria) end yield(doc) end