Class: MongoDoc::Criteria

Inherits:
Object show all
Includes:
Enumerable
Defined in:
lib/mongodoc/criteria.rb

Overview

The Criteria class is the core object needed in Mongoid to retrieve objects from the database. It is a DSL that essentially sets up the selector and options arguments that get passed on to a Mongo::Collection in the Ruby driver. Each method on the Criteria returns self to they can be chained in order to create a readable criterion to be executed against the database.

Example setup:

criteria = Criteria.new

criteria.only(:field => "value").only(:field).skip(20).limit(20)

criteria.execute

Constant Summary collapse

SORT_REVERSALS =
{
  :asc => :desc,
  :ascending => :descending,
  :desc => :asc,
  :descending => :ascending
}
AGGREGATE_REDUCE =
"function(obj, prev) { prev.count++; }"
GROUP_REDUCE =
"function(obj, prev) { prev.group.push(obj); }"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(klass) ⇒ Criteria

Create the new Criteria object. This will initialize the selector and options hashes, as well as the type of criteria.

Options:

klass: The class to execute on.



36
37
38
# File 'lib/mongodoc/criteria.rb', line 36

def initialize(klass)
  @selector, @options, @klass = {}, {}, klass
end

Instance Attribute Details

#collectionObject (readonly)

Returns the value of attribute collection.



28
29
30
# File 'lib/mongodoc/criteria.rb', line 28

def collection
  @collection
end

#klassObject (readonly)

Returns the value of attribute klass.



28
29
30
# File 'lib/mongodoc/criteria.rb', line 28

def klass
  @klass
end

#optionsObject (readonly)

Returns the value of attribute options.



28
29
30
# File 'lib/mongodoc/criteria.rb', line 28

def options
  @options
end

#selectorObject (readonly)

Returns the value of attribute selector.



28
29
30
# File 'lib/mongodoc/criteria.rb', line 28

def selector
  @selector
end

Class Method Details

.translate(klass, params = {}) ⇒ Object

Translate the supplied arguments into a Criteria object.

If the passed in args is a single String, then it will construct an id Criteria from it.

If the passed in args are a type and a hash, then it will construct the Criteria with the proper selector, options, and type.

Options:

args: either a String or a Symbol, +Hash combination.

Example:

Criteria.translate(Person, "4ab2bc4b8ad548971900005c")

Criteria.translate(Person, :conditions => { :field => "value"}, :limit => 20)

Returns a new Criteria object.



444
445
446
447
# File 'lib/mongodoc/criteria.rb', line 444

def self.translate(klass, params = {})
  return new(klass).id(params).one unless params.is_a?(Hash)
  return new(klass).criteria(params)
end

Instance Method Details

#==(other) ⇒ Object

Returns true if the supplied Enumerable or Criteria is equal to the results of this Criteria or the criteria itself.

This will force a database load when called if an enumerable is passed.

Options:

other: The other Enumerable or Criteria to compare to.



48
49
50
51
52
53
54
55
56
57
58
# File 'lib/mongodoc/criteria.rb', line 48

def ==(other)
  case other
  when Criteria
    self.selector == other.selector && self.options == other.options
  when Enumerable
    @collection ||= execute
    return (collection == other)
  else
    return false
  end
end

#aggregateObject

Aggregate the criteria. This will take the internally built selector and options and pass them on to the Ruby driver’s group() method on the collection. The collection itself will be retrieved from the class provided, and once the query has returned it will provided a grouping of keys with counts.

Example:

criteria.only(:field1).where(:field1 => "Title").aggregate



69
70
71
# File 'lib/mongodoc/criteria.rb', line 69

def aggregate
  klass.collection.group(options[:fields], selector, { :count => 0 }, AGGREGATE_REDUCE, true)
end

#allObject

Get all the matching documents in the database for the Criteria.

Example:

criteria.all

Returns: Array



80
81
82
# File 'lib/mongodoc/criteria.rb', line 80

def all
  collect
end

#countObject

Get the count of matching documents in the database for the Criteria.

Example:

criteria.count

Returns: Integer



91
92
93
# File 'lib/mongodoc/criteria.rb', line 91

def count
  @count ||= klass.collection.find(selector, options.dup).count
end

#criteria(criteria_conditions = {}) ⇒ Object

Translate the supplied argument hash

Options:

criteria_conditions: Hash of criteria keys, and parameter values

Example:

criteria.criteria(:where => { :field => "value"}, :limit => 20)

Returns self



169
170
171
172
173
174
# File 'lib/mongodoc/criteria.rb', line 169

def criteria(criteria_conditions = {})
  criteria_conditions.each do |(key, value)|
    send(key, value)
  end
  self
end

#each(&block) ⇒ Object

Iterate over each Document in the results and pass each document to the block.

Example:

criteria.each { |doc| p doc }



101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/mongodoc/criteria.rb', line 101

def each(&block)
  @collection ||= execute
  if block_given?
    container = []
    collection.each do |item|
      container << item
      yield item
    end
    @collection = container
  end
  self
end

#every(selections = {}) ⇒ Object

Adds a criterion to the Criteria that specifies values that must all be matched in order to return results. Similar to an “in” clause but the underlying conditional logic is an “AND” and not an “OR”. The MongoDB conditional operator that will be used is “$all”.

Options:

selections: A Hash where the key is the field name and the value is an Array of values that must all match.

Example:

criteria.every(:field => ["value1", "value2"])

criteria.every(:field1 => ["value1", "value2"], :field2 => ["value1"])

Returns: self



193
194
195
# File 'lib/mongodoc/criteria.rb', line 193

def every(selections = {})
  selections.each { |key, value| selector[key] = { "$all" => value } }; self
end

#excludes(exclusions = {}) ⇒ Object

Adds a criterion to the Criteria that specifies values that are not allowed to match any document in the database. The MongoDB conditional operator that will be used is “$ne”.

Options:

excludes: A Hash where the key is the field name and the value is a value that must not be equal to the corresponding field value in the database.

Example:

criteria.excludes(:field => "value1")

criteria.excludes(:field1 => "value1", :field2 => "value1")

Returns: self



213
214
215
# File 'lib/mongodoc/criteria.rb', line 213

def excludes(exclusions = {})
  exclusions.each { |key, value| selector[key] = { "$ne" => value } }; self
end

#extras(extras) ⇒ Object

Adds a criterion to the Criteria that specifies additional options to be passed to the Ruby driver, in the exact format for the driver.

Options:

extras: A Hash that gets set to the driver options.

Example:

criteria.extras(:limit => 20, :skip => 40)

Returns: self



229
230
231
232
233
# File 'lib/mongodoc/criteria.rb', line 229

def extras(extras)
  options.merge!(extras)
  filter_options
  self
end

#groupObject

Groups the criteria. This will take the internally built selector and options and pass them on to the Ruby driver’s group() method on the collection. The collection itself will be retrieved from the class provided, and once the query has returned it will provided a grouping of keys with objects.

Example:

criteria.only(:field1).where(:field1 => "Title").group



123
124
125
126
127
128
129
130
131
# File 'lib/mongodoc/criteria.rb', line 123

def group
  klass.collection.group(
    options[:fields],
    selector,
    { :group => [] },
    GROUP_REDUCE,
    true
  ).collect {|docs| docs["group"] = MongoDoc::BSON.decode(docs["group"]); docs }
end

#id(id_or_object_id) ⇒ Object

Adds a criterion to the Criteria that specifies an id that must be matched.

Options:

id_or_object_id: A String representation of a Mongo::ObjectID

Example:

criteria.id("4ab2bc4b8ad548971900005c")

Returns: self



246
247
248
249
250
251
# File 'lib/mongodoc/criteria.rb', line 246

def id(id_or_object_id)
  if id_or_object_id.kind_of?(String)
    id_or_object_id = Mongo::ObjectID.from_string(id_or_object_id)
  end
  selector[:_id] = id_or_object_id; self
end

#in(inclusions = {}) ⇒ Object

Adds a criterion to the Criteria that specifies values where any can be matched in order to return results. This is similar to an SQL “IN” clause. The MongoDB conditional operator that will be used is “$in”.

Options:

inclusions: A Hash where the key is the field name and the value is an Array of values that any can match.

Example:

criteria.in(:field => ["value1", "value2"])

criteria.in(:field1 => ["value1", "value2"], :field2 => ["value1"])

Returns: self



269
270
271
# File 'lib/mongodoc/criteria.rb', line 269

def in(inclusions = {})
  inclusions.each { |key, value| selector[key] = { "$in" => value } }; self
end

#lastObject

Return the last result for the Criteria. Essentially does a find_one on the collection with the sorting reversed. If no sorting parameters have been provided it will default to ids.

Example:

Criteria.only(:name).where(:name = "Chrissy").last



140
141
142
143
144
145
146
# File 'lib/mongodoc/criteria.rb', line 140

def last
  opts = options.dup
  sorting = opts[:sort]
  sorting = [[:_id, :asc]] unless sorting
  opts[:sort] = sorting.collect { |option| [ option.first, Criteria.invert(option.last) ] }
  klass.collection.find_one(selector, opts)
end

#limit(value = 20) ⇒ Object

Adds a criterion to the Criteria that specifies the maximum number of results to return. This is mostly used in conjunction with skip() to handle paginated results.

Options:

value: An Integer specifying the max number of results. Defaults to 20.

Example:

criteria.limit(100)

Returns: self



286
287
288
# File 'lib/mongodoc/criteria.rb', line 286

def limit(value = 20)
  options[:limit] = value; self
end

#not_in(exclusions) ⇒ Object

Adds a criterion to the Criteria that specifies values where none should match in order to return results. This is similar to an SQL “NOT IN” clause. The MongoDB conditional operator that will be used is “$nin”.

Options:

exclusions: A Hash where the key is the field name and the value is an Array of values that none can match.

Example:

criteria.not_in(:field => ["value1", "value2"])

criteria.not_in(:field1 => ["value1", "value2"], :field2 => ["value1"])

Returns: self



306
307
308
# File 'lib/mongodoc/criteria.rb', line 306

def not_in(exclusions)
  exclusions.each { |key, value| selector[key] = { "$nin" => value } }; self
end

#offsetObject

Returns the offset option. If a per_page option is in the list then it will replace it with a skip parameter and return the same value. Defaults to 20 if nothing was provided.



313
314
315
# File 'lib/mongodoc/criteria.rb', line 313

def offset
  options[:skip]
end

#oneObject Also known as: first

Return the first result for the Criteria.

Example:

Criteria.only(:name).where(:name = "Chrissy").one



153
154
155
# File 'lib/mongodoc/criteria.rb', line 153

def one
  klass.collection.find_one(selector, options.dup)
end

#only(*args) ⇒ Object

Adds a criterion to the Criteria that specifies the fields that will get returned from the Document. Used mainly for list views that do not require all fields to be present. This is similar to SQL “SELECT” values.

Options:

args: A list of field names to retrict the returned fields to.

Example:

criteria.only(:field1, :field2, :field3)

Returns: self



373
374
375
# File 'lib/mongodoc/criteria.rb', line 373

def only(*args)
  options[:fields] = args.flatten if args.any?; self
end

#order_by(params = []) ⇒ Object

Adds a criterion to the Criteria that specifies the sort order of the returned documents in the database. Similar to a SQL “ORDER BY”.

Options:

params: An Array of [field, direction] sorting pairs.

Example:

criteria.order_by([[:field1, :asc], [:field2, :desc]])

Returns: self



329
330
331
# File 'lib/mongodoc/criteria.rb', line 329

def order_by(params = [])
  options[:sort] = params; self
end

#pageObject

Either returns the page option and removes it from the options, or returns a default value of 1.



335
336
337
338
339
340
341
# File 'lib/mongodoc/criteria.rb', line 335

def page
  if options[:skip] && options[:limit]
    (options[:skip].to_i + options[:limit].to_i) / options[:limit].to_i
  else
    1
  end
end

#paginateObject

Executes the Criteria and paginates the results.

Example:

criteria.paginate



348
349
350
351
352
353
# File 'lib/mongodoc/criteria.rb', line 348

def paginate
  @collection ||= execute
  WillPaginate::Collection.create(page, per_page, count) do |pager|
    pager.replace(collection.to_a)
  end
end

#per_pageObject

Returns the number of results per page or the default of 20.



356
357
358
# File 'lib/mongodoc/criteria.rb', line 356

def per_page
  (options[:limit] || 20).to_i
end

#skip(value = 0) ⇒ Object

Adds a criterion to the Criteria that specifies how many results to skip when returning Documents. This is mostly used in conjunction with limit() to handle paginated results, and is similar to the traditional “offset” parameter.

Options:

value: An Integer specifying the number of results to skip. Defaults to 0.

Example:

criteria.skip(20)

Returns: self



391
392
393
# File 'lib/mongodoc/criteria.rb', line 391

def skip(value = 0)
  options[:skip] = value; self
end

#where(selector_or_js = {}) ⇒ Object Also known as: and, conditions

Adds a criterion to the Criteria that specifies values that must be matched in order to return results. This is similar to a SQL “WHERE” clause. This is the actual selector that will be provided to MongoDB, similar to the Javascript object that is used when performing a find() in the MongoDB console.

Options:

selector_or_js: A Hash that must match the attributes of the Document or a String of js code.

Example:

criteria.where(:field1 => "value1", :field2 => 15)

criteria.where('this.a > 3')

Returns: self



413
414
415
416
417
418
419
420
421
# File 'lib/mongodoc/criteria.rb', line 413

def where(selector_or_js = {})
  case selector_or_js
  when String
    selector['$where'] = selector_or_js
  else
    selector.merge!(selector_or_js)
  end
  self
end