46

This must be asked alot but it is very poorly documented. There is no mention at http://mongoid.org/en/mongoid/docs/querying.html

I'm trying to check whether a user exists (below is an AND query), how can I change it to an OR type query

Username.where(:username=>@username, :email=>@email)

(Either the email or the username must match).

I have found some pretty complicated ways online including sending a direct javascript (from): http://omarqureshi.net/articles/2010-6-17-using-or-in-mongoid

Surely there must be a simple clear syntax to do this correctly?

Tarang
  • 75,157
  • 39
  • 215
  • 276

5 Answers5

124

For the sake of others who end up on this page, the updated syntax is now

Username.or({username: @username}, {email: @email})

Please refer to the updated docs or relevant impl.

James Lim
  • 12,915
  • 4
  • 40
  • 65
  • 11
    In scopes you still have to use `any_of` otherwise it will throw a syntax error. – aledalgrande Apr 02 '14 at 19:06
  • 1
    Link posted doesn't tell anything about `.or` nor `any_of`, please refer [here](https://github.com/mongodb/mongoid/blob/master/lib/mongoid/criteria/queryable/selectable.rb) to see detailed documentation and implementation – silva96 Jun 02 '16 at 12:47
  • you can also use self.or in scopes (because `or` is a keyword in ruby) – Shiyason Apr 12 '17 at 20:49
55

Yeah, this used to be documented better. Try this:

Username.any_of({:username => @username},
                {:email => @email})
Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
9

There is a typo in @miguel-savignano's response. According to Stackoverflow the "edit queue is full", which is why I didn't submit an edit.

Proper syntax:

Username.or({username: @username}).or({email: @email})

A more concise solution:

Username.or({username: @username}, {email: @email})

The Mongo selector will resolve to:

{"$or"=>[{"username"=>@username}, {"email"=>@email}]}

I found this question as I was trying to solve for creating "or" queries.

If you are looking to match a string or any one of an array of elements, then you will need to write a Mongoid query with the Mongo '$in' selector.

For example, you have a specific username and an array of emails. You would like to return all results where at least one of the fields matches either the username or one of the emails within the array.

@username = "jess"
@emails = ["hi@mail.com", "test@mail.com", "foo@mail.com"]
User.or({username: ""}, {email: {'$in': @emails}})

The Mongo selector will resolve to:

{"$or"=>[{"first_name"=>""}, {"email"=>{:$in=>["hi@mail.com", "test@mail.com", "foo@mail.com"]}}]}
  • If you have Users with 2 of the 3 emails in your database, then the selector will return a count of 2.
  • If you have a User with the username "jess" and 3 additional Users each with one of the given emails, then the selector will return a count of 4.
Laura
  • 93
  • 1
  • 6
9

Also, in Mongoid 5.0, if you still want to use the where method, use the following

Username.where('$or' => [ { username: @username }, { email: @email } ])

this is very useful when you are building a kind of query hash in a dynamic way and you need to keep the where method

Johan Tique
  • 141
  • 2
  • 3
7

In Mongoid 5.0, this works for me

Username.or({username: @username}).or({email: @email})
uzaif
  • 3,511
  • 2
  • 21
  • 33
miguel savignano
  • 1,109
  • 13
  • 9