RailsApps/rails3-mongoid-devise — pull request #19 by nrser (2012-05-07 04:03:24+00:00)
Title: Improve user model for db scalability

hi, i've been using this app as the starting point to get up to speed with Rails and MongoDB (thanks, it's been a great help).

i'm fairly new to both these technologies, but have a background in web apps and scaling (built and ran the initial version of Zynga's data layer), and from what i've tested and read, i think you may want to consider these changes:

**1. remove the uniqueness constraint on the `email` and `name` fields of the `User` model.**

i removed this line from `user.rb`:

```ruby
validates_uniqueness_of :name, :email, :case_sensitive => false
```

the big issue is the `case_insensitive` option... Mongo can't build case insensitive indexes at this point, which means you'll get a full index scan against a case-insensitive regex at best:

https://jira.mongodb.org/browse/SERVER-90

with regards to the `email` field, Devise downcases the email address and checks it's uniqueness already, so the `validates_uniqueness_of` is unnecessary. also, note that when Devise runs the operation, it uses

```ruby
rails3_mongoid_devise_development['$cmd'].find({"count"=>"users", "query"=>{:email=>"neil@test.com"}, "fields"=>nil}).limit(-1)
```

which should be able to take full advantage of an index on `email`, versus the query the model validation was running

```ruby
rails3_mongoid_devise_development['$cmd'].find({"count"=>"users", "query"=>{:email=>/^neil@test\.com$/i}, "fields"=>nil}).limit(-1)
```

which has to scan the entire index due to the regex.

as far as the `name` field is concerned: due to the lack of case-insensitive indexing, it doesn't seem like good practice to have a field that is case-insensitive and unique without storing a case-insensitive version to index and query against.

considering `name` seems to be thrown in as a simple example of adding a field, and guessing that most developers will assume it represents a person's real name (which shouldn't be unique), the best solution seemed to be to remove the constraint.

**2. added an index on the `email` field**

Devise queries against this on login.

like i said, i'm new to both of these techs and may be completely wrong, but these are the things i noticed thus far and i wanted to contribute them back.