Alex Rivera | Logout

N+1 problem in mongoid

Asked 2010-10-12T08:16:14.250
13

I'm using Mongoid to work with MongoDB in Rails.

What I'm looking for is something like active record include. Currently I failed to find such method in mongoid orm.

Anybody know how to solve this problem in mongoid or perhaps in mongomapper, which is known as another good alternative.

Edit
Report

3 Answers

17

Now that some time has passed, Mongoid has indeed added support for this. See the "Eager Loading" section here:
http://docs.mongodb.org/ecosystem/tutorial/ruby-mongoid-tutorial/#eager-loading

Band.includes(:albums).each do |band|
  p band.albums.first.name # Does not hit the database again.
end

I'd like to point out:

  1. Rails' :include does not do a join
  2. SQL and Mongo both need eager loading.
  3. The N+1 problem happens in this type of scenario (query generated inside of loop):

.

<% @posts.each do |post| %>
  <% post.comments.each do |comment| %>
    <%= comment.title %>
  <% end %>
<% end %>

Looks like the link that @amrnt posted was merged into Mongoid.

answered 2011-10-11T21:42:47.177
12

Update: it's been two years since I posted this answer and things have changed. See tybro0103's answer for details.


Old Answer

Based on the documentation of both drivers, neither of them supports what you're looking for. Probably because it wouldn't solve anything.

The :include functionality of ActiveRecord solves the N+1 problem for SQL databases. By telling ActiveRecord which related tables to include, it can build a single SQL query, by using JOIN statements. This will result in a single database call, regardless of the amount of tables you want to query.

MongoDB only allows you to query a single collection at a time. It doesn't support anything like a JOIN. So even if you could tell Mongoid which other collections it has to include, it would still have to perform a separate query for each additional collection.

answered 2010-10-12T08:39:56.170
0

Embed the detail records/documents in the master record/document.

answered 2010-10-13T18:50:15.233

Your Answer