I'm using Mongoid to work with MongoDB. Everything is fine, I like it very much and so on. In my blog application (posts controller, index action) I have this code:
@posts = Post.without(:comments)
@posts = @posts.my_search(params[:s]) if params[:s]
@posts = @posts.order_by([:created_at, :desc])
@posts = @posts.where(:pid.lt => params[:p].to_i+1) if params[:p]
@posts = @posts.limit(items_per_page+1)
The part with "where" is implementation of my own pagination method (allows to page results in one direction only, but without skip()
, what I consider a plus). Now, there are few small problems that make me feel uncomfortable:
For my pagination to work I need to get the last post within that limit. But when I do @posts.last
I'm getting last document of the whole query without limit. Ok, this is strange, but not a big problem. Other than that, query results act like almost-ordinary-array, so at this moment I'm getting the last element with @posts.pop
(funny, but it doesn't remove any documents) or @posts.fetch(-1)
I have a feeling that this isn't "right way" and there mush be something more elegant. Also
@posts.count
generates second query exactly the same as first one (without limit) but with "count" only and I don't like it.
If I make the last line look like
@posts = @posts.limit(items_per_page+1).to_ary
to convert query results into array, everything generates only one query (good), but now @posts.count
stops reporting what I need (total amount of documents without limit applied) and behaves exactly like @posts.size
- it returns items_per_page+1
or less (bad).
So, here are my questions:
Getting the last document:
Post.last
Getting last document with some other queries:
Post.order_by([:created_at, :desc]).last
Getting total number documents:
Post.order_by([:created_at, :desc]).count
Recommendation: Just use the built in pagination
@posts = Post.limit(10).paginate(:page=>pararms[:page])
later:
<%= will_paginate @posts %>
Regarding the additional queries -- mongoid lazy loads everything:
@posts = Post.all #no query has been run yet
@posts.first #Ok, a query has finally been run because you are accessing the objects