Selection
Origin provides a DSL for selection of documents in MongoDB, and supports all
operations that MongoDB provides. As you build your queries, you can always
access the raw selector by calling Queryable#selector
.
Standard
The following is a table of all selection operations and their corresponding MongoDB selector.
Operation | Origin | Selector |
---|---|---|
Queryable#all
Add $all selection. Documents must match all values
provided in the array. Also can be written with:
|
queryable.all(field: [ 1, 2, 3 ]) queryable.all(field: [ /(1|2|3)/ ]) |
{ "field" => { "$all" => [ 1, 2, 3 ]}} { "field" => { "$all" => [ /(1|2|3)/ ]}} |
Queryable#and
Add $and selection. Documents must match all the criteria provided. |
queryable.and( { name: "Syd" }, { active: true } ) |
{ "$and" => [ { "name" => "Syd" }, { "active" => true } ] } |
Queryable#between
Add $gte/$lte selection. Finds documents with values between the lower and upper bound of the range. |
queryable.between(age: 18..30) |
{ "age" => { "$gte" => 18, "$lte" => 30 }} |
Queryable#elem_match
Add $elemMatch selection. Finds documents with arrays of values that match the provided expression. |
queryable.elem_match(members: { name: "Syd" }) |
{ "members" => { "$elemMatch" => { "name" => "Syd" }}} |
Queryable#exists
Add $exists selection. Matches documents based on whether a value
for the field exists or not. Will match docs with |
queryable.exists(name: true) |
{ "name" => { "$exists" => true }} |
Queryable#gt
Add $gt selection. Matches documents who's field is greater than the provided value. |
queryable.gt(age: 18) |
{ "age" => { "$gt" => 18 }} |
Queryable#gte
Add $gte selection. Matches documents who's field is greater than or equal to the provided value. |
queryable.gte(age: 18) |
{ "age" => { "$gte" => 18 }} |
Queryable#in
Add $in selection. Matches documents who's field contains a
value that is in the array, similar to a SQL IN. Also
can be written as: |
queryable.in(name: [ "Syd", "Nancy" ]) |
{ "name" => { "$in" => [ "Syd", "Nancy" ]}} |
Queryable#lt
Add $lt selection. Matches documents who's field is less than the provided value. |
queryable.lt(age: 18) |
{ "age" => { "$lt" => 18 }} |
Queryable#lte
Add $lte selection. Matches documents who's field is less than or equal to the provided value. |
queryable.lte(age: 18) |
{ "age" => { "$lte" => 18 }} |
Queryable#max_distance
Add $maxDistance selection. This can only be used in conjunction
with |
queryable. near(location: [ 20, 20 ]). max_distance(location: 0.5) |
{ "location" => { "$near" => [ 20, 20 ], "$maxDistance" => 0.5 } } |
Queryable#mod
Add $mod selection. Matches documents who's field matches the modulo value. |
queryable.mod(field: [ 10, 1 ]) |
{ "field" => { "$mod" => [ 10, 1 ]}} |
Queryable#ne
Add $ne selection. Matches documents who's field is not equal to the provided value. |
queryable.ne(name: "Nancy") |
{ "name" => { "$ne" => "Nancy" }} |
Queryable#near
Add $near selection. Matches documents who's geo location is near the provided coordinates. |
queryable.near(location: [ 23.1, 12.1 ]) |
{ "location" => { "$near" => [ 23.1, 12.1 ] }} |
Queryable#near_sphere
Add $nearSphere selection. Matches documents who's geo location is near the provided coordinates using spherical algorithms. |
queryable.near_sphere(location: [ 23.1, 12.1 ]) |
{ "location" => { "$nearSphere" => [ 23.1, 12.1 ] }} |
Queryable#nin
Add $nin selection. Matches documents who's field does not match values in the provided array. |
queryable.nin(name: [ "Dave", "Martin" ]) |
{ "name" => { "$nin" => [ "Dave", "Martin" ] }} |
Queryable#nor
Add $nor selection. Matches documents who do not match at least one of the provided criteria. |
queryable.nor( { name: "Martin" }, { name: "Dave" } ) |
{ "$nor" => [ { "name" => "Martin" }, { "name" => "Dave" } ] } |
Queryable#or
Add $or selection. Matches documents who match at least one of the provided criteria. |
queryable.or( { name: "Martin" }, { name: "Dave" } ) |
{ "$or" => [ { "name" => "Martin" }, { "name" => "Dave" } ] } |
Queryable#where
Add $where selection or standard document matching. If provided a string, we assume this is javascript and use $where. When a hash is provided this is a standard selection. |
queryable.where(name: "Syd") queryable.where("this.name == 'Syd'") |
{ "name" => "Syd" } { "$where" => "this.name == 'Syd'" } |
Queryable#with_size
Add $size selection. Matches documents who's array field has
the exact size of the provided value. This is named
|
queryable.with_size(members: 3) |
{ "members" => { "$size" => 3 }} |
Queryable#with_type
Add $type selection. Matches documents who's field is of the provided BSON type. See BSON Types for a complete list. |
queryable.with_type(name: 2) |
{ "name" => { "$type" => 2 }} |
Queryable#within_box
Adds $within/$box selection. Matches documents that have geo locations inside the provided box. |
queryable.within_box( location: [[ 1, 10 ], [ 10, 1 ]] ) |
{ "location" => { "$within" => { "$box" => [[ 1, 10 ], [ 10, 1 ]]} } } |
Queryable#within_circle
Adds $within/$center selection. Matches documents that have geo locations inside the provided circle with a radius. |
queryable.within_circle( location: [[ 1, 10 ], 0.5 ] ) |
{ "location" => { "$within" => { "$center" => [[ 1, 10 ], 0.5 ]} } } |
Queryable#within_polygon
Adds $within/$polygon selection. Matches documents that have geo locations inside the provided polygon. |
queryable.within_polygon( location: [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ] ) |
{ "location" => { "$within" => { "$polygon" => [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ] } } } |
Queryable#within_spherical_circle
Adds $within/$centerSphere selection. Matches documents that have geo locations inside the provided sphere with a radius. |
queryable.within_spherical_circle( location: [[ 1, 10 ], 0.5 ] ) |
{ "location" => { "$within" => { "$centerSphere" => [[ 1, 10 ], 0.5 ]} } } |
Negation
You can negate any selection by placing a not
immediately
in front of the selection you want to invert. This will add a $not
clause to the query.
Note that |
queryable.not.gt(age: 50) queryable.selector #=> { "age" => { "$not" => { "$gt" => 50 }}}
Symbol Operators
As a convenience in where
queries, Mongoid provides methods
on symbol that generate more complex MongoDB operations. All symbol methods
are listed in the following table, with their corresponding selectors.
Operation | Origin | Selector |
---|---|---|
Symbol#all
Add $all selection. Documents must match all values provided in the array. |
queryable.where(:field.all => [ 1, 2, 3 ]) |
{ "field" => { "$all" => [ 1, 2, 3 ]}} |
Symbol#elem_match
Add $elemMatch selection. Finds documents with arrays of values that match the provided expression. |
queryable.where( :members.elem_match => { name: "Syd" } ) |
{ "members" => { "$elemMatch" => { "name" => "Syd" } } } |
Symbol#exists
Add $exists selection. Matches documents based on whether a value
for the field exists or not. Will match docs with |
queryable.where(:name.exists => true) |
{ "name" => { "$exists" => true }} |
Symbol#gt
Add $gt selection. Matches documents who's field is greater than the provided value. |
queryable.where(:age.gt => 18) |
{ "age" => { "$gt" => 18 }} |
Symbol#gte
Add $gte selection. Matches documents who's field is greater than or equal to the provided value. |
queryable.where(:age.gte => 18) |
{ "age" => { "$gte" => 18 }} |
Symbol#in
Add $in selection. Matches documents who's field contains a value that is in the array, similar to a SQL IN. |
queryable.where(:name.in => [ "Syd", "Nancy" ]) |
{ "name" => { "$in" => [ "Syd", "Nancy" ]}} |
Symbol#lt
Add $lt selection. Matches documents who's field is less than the provided value. |
queryable.where(:age.lt => 18) |
{ "age" => { "$lt" => 18 }} |
Symbol#lte
Add $lte selection. Matches documents who's field is less than or equal to the provided value. |
queryable.where(:age.lte => 18) |
{ "age" => { "$lte" => 18 }} |
Symbol#mod
Add $mod selection. Matches documents who's field matches the modulo value. |
queryable.where(:field.mod => [ 10, 1 ]) |
{ "field" => { "$mod" => [ 10, 1 ]}} |
Symbol#ne
Add $ne selection. Matches documents who's field is not equal to the provided value. |
queryable.where(:name.ne => "Nancy") |
{ "name" => { "$ne" => "Nancy" }} |
Symbol#near
Add $near selection. Matches documents who's geo location is near the provided coordinates. |
queryable.where(:location.near => [ 23.1, 12.1 ]) |
{ "location" => { "$near" => [ 23.1, 12.1 ] }} |
Symbol#near_sphere
Add $nearSphere selection. Matches documents who's geo location is near the provided coordinates using spherical algorithms. |
queryable.where( :location.near_sphere => [ 23.1, 12.1 ] ) |
{ "location" => { "$nearSphere" => [ 23.1, 12.1 ] }} |
Symbol#nin
Add $nin selection. Matches documents who's field does not match values in the provided array. |
queryable.where(:name.nin => [ "Dave", "Martin" ]) |
{ "name" => { "$nin" => [ "Dave", "Martin" ] }} |
Symbol#with_size
Add $size selection. Matches documents who's array field has
the exact size of the provided value. This is named
|
queryable.where(:members.with_size => 3) |
{ "members" => { "$size" => 3 }} |
Symbol#with_type
Add $type selection. Matches documents who's field is of the provided BSON type. See BSON Types for a complete list. |
queryable.where(:name.with_type => 2) |
{ "name" => { "$type" => 2 }} |
Symbol#within_box
Adds $within/$box selection. Matches documents that have geo locations inside the provided box. |
queryable.where( :location.within_box => [[ 1, 10 ], [ 10, 1 ]] ) |
{ "location" => { "$within" => { "$box" => [[ 1, 10 ], [ 10, 1 ]]} } } |
Symbol#within_circle
Adds $within/$center selection. Matches documents that have geo locations inside the provided circle with a radius. |
queryable.where( :location.within_circle => [[ 1, 10 ], 0.5 ] ) |
{ "location" => { "$within" => { "$center" => [[ 1, 10 ], 0.5 ]} } } |
Symbol#within_polygon
Adds $within/$polygon selection. Matches documents that have geo locations inside the provided polygon. |
queryable.where( :location.within_polygon => [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ] ) |
{ "location" => { "$within" => { "$polygon" => [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ] } } } |
Symbol#within_spherical_circle
Adds $within/$centerSphere selection. Matches documents that have geo locations inside the provided sphere with a radius. |
queryable.where( :location.within_spherical_circle => [[ 1, 10 ], 0.5 ] ) |
{ "location" => { "$within" => { "$centerSphere" => [[ 1, 10 ], 0.5 ]} } } |
Merge Strategies
Explicit Merging
The selection API also provides merge strategies for cases you want to
override the default behaviour with specific methods that expect array values.
The available strategies are *intersect, override, and union* and are used by
chaining the name of the strategy before calling any method. For example,
to override the default intersection behaviour of #in
:
Band.in(name: [ "Depeche Mode" ]).union.in(name: [ "New Order" ])
This translates to the following selector.
{ "name" => { "$in" => [ "Depeche Mode", "New Order" ] }}
The default behaviour for the array methods are:
Queryable#all
- defaults tounion
.Queryable#in
- defaults tointersect
.Queryable#nin
- defaults tointersect
.
The available strategies are:
Queryable#intersect
Performs an intersection of existing and new array.Queryable#override
Overwrites the old array with the new.Queryable#union
Performs a union of the existing and new array.
Automatic Merging
When using the normal Origin DSL, criterion on the same field with different operators will automatically be merged into a complex selector on the common field. For example:
likeable = Band.gt(likes: 100).lt(likes: 1000).ne(likes: 500) likeable.selector #=> { "likes" => { "$gt" => 100, "$lt" => 1000, "$ne" => 500 }}
Note that this works only when using the DSL methods, but not currently
when using the symbol operators in a where
clause.
likeable = Band.where(:likes.gt => 100, :likes.lt => 1000, :likes.ne => 500) likeable.selector #=> { "likes" => { "$ne" => 500 }}