开发者

How does Mongoid "criteria" work?

I'm trying to do something straight forward such as:

User.all(:criteria => {:project_id 开发者_如何学C=> 2})

This returns an instance of Mongoid::Criteria

What can I do with this criteria? What if I just want the array of documents returned for further evaluation?


In Mongoid, the criteria represents the query, not the elements. You can think of a criteria as a filter, a scope, a query object.

Once you have a criteria (scope), you can get the elements, executing an actual query to the database, with a method that is supposed to iterate over the elements or return one element, for example: .first, .last, .to_a, .each, .map, etc.

This is more efficient and allows you to compose a complex "query" from other simple ones.

For example, you can create some named scopes in your class:

class User
  include Mongoid::Document
  field :name,  type: String
  field :age,   type: Integer
  field :admin, type: Boolean

  scope :admins, where(admin: true) # filter users that are admins
  scope :with_name, (name)-> { where(name: name) } # filter users with that name
end

Then you can create some criteria objects:

admins      = User.admins
johns       = User.with_name('John')
admin_johns = User.admins.with_name('John') # composition of criterias, is like doing ANDs
young       = User.where(:age.lt => 25) # the Mongoid method .where also returns a criteria

Up to this point, you didn't fire any query to the mongo database, you were just composing queries.

At any time, you can keep chaining criterias, to refine the query even further:

young_admins = admins.merge(young)
old_admins = admins.where(age.gt => 60)

And finally, get the Array with the elements:

# Execute the query and an array from the criteria
User.all.to_a
User.admins.to_a
admins.to_a
young_admins.to_a

# Execute the query but only return one element
User.first
admins.first
johns.last

# Execute the query and iterate over the returned elements
User.each{|user| ... }
User.admins.each{|admin_user| ... }
johns.map{|john_user| ... }

So, define some named scopes in the Class, then use them to create a criteria, and do the real query when you need it (lazy loading). Criterias handle all of this for you even if you didn't know you needed it.


Criteria is something like Relation object in ActiveRecord

You can use it this way

users = User.where(:project_id => 2)
users.each do |user|
  puts user.name
end
# or
users.all

This will return [] if there is no any user

users.all.each do |user|
  puts user.name
end


To get an array from a Mongoid::Criteria: use the method .to_a

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜