Mongoid で or 条件を組むには any_of を使う。
Model.any_of({:label => /foo/}, {:name => /foo/})
=> #<Mongoid::Criteria
selector: {"$or"=>[{"label"=>/foo/}, {"name"=>/foo/}]}
options: {}
class: Model
embedded: false>
Mongoid で and 条件を組むには all_of を使う。
Model.all_of({:label => /foo/}, {:name => /foo/})
=> #<Mongoid::Criteria
selector: {"$and"=>[{"label"=>/foo/}, {"name"=>/foo/}]}
options: {}
class: Model
embedded: false>
では、(A or B) and (C or D) のような、or 条件の and 条件(またはその逆)はどのように組めば良いか? any_of や all_of ではサポートされていないようだ。
実は、直接 Mongoid::Criteria を作って組み立てるという裏技で実現することができる。Criteria#selector はただのハッシュなので自分で簡単に組み立てられるのだ。
criteria = Mongoid::Criteria.new(Model)
or_selector1 = {"$or"=>[{"label"=>/foo/}, {"name"=>/foo/}]}
or_selector2 = {"$or"=>[{"label"=>/bar/}, {"name"=>/bar/}]}
and_selector = {"$and"=>[or_selector1, or_selector2]}
criteria.selector = and_selector
criteria
=> #<Mongoid::Criteria
selector: {"deleted_at"=>nil, "$and"=>[
{"$or"=>[{"label"=>/foo/}, {"name"=>/foo/}]},
{"$or"=>[{"label"=>/bar/}, {"name"=>/bar/}]}
]}
options: {}
class: Model
embedded: false>
あとは criteria.first
とかするとクエリが投げられて結果が返ってくる。便利。