Take the 2-minute tour ×

I need to rank posts in a Rails application using Mongoid and I am looking for input on how to go about doing it efficiently and accurately.

Right now, the way I made it up is highly inefficient.

Right now I am sorting models based on methods like this:

def hotness
  return (self.confidence*(self.popularity+0.3))/Math.sqrt((Time.now - Time.at(self.created_at)))

So then I am sorting an array based on hotness and printing that to the page. This is the wrong way to go about it and performance is just not happening right now.

I am not really sure what a better way to go about it would be though.

There are other functions that do not require time called and I could imagine different ways to do those, but would still like input. Optimization is important to me.

Thanks a lot in advance. I can clarify anything if needed.

share|improve this question
What exactly are you looking for? A different type of ranking algorithm altogether? Just performance improvements without changing the actual behavior? –  Beerlington Feb 14 '13 at 23:01
So you want to do the ordering in the Mongoid query? –  PinnyM Feb 14 '13 at 23:10
I would like to know whether there is a more efficient way to return a result than this. Would the best move to be to put this result into a field and then update that periodically? That seems like a possible solution, then I would only have to query one sortable number, but I am looking for any input that can help me make the right choice. –  spitfire109 Feb 14 '13 at 23:20

1 Answer 1

Following on from your comment above - if this is the sort of result that can be cached in a field an updated periodically, or whenever the model is saved - then that is the best way to go (in terms of query performance in MongoDB).

So you'd end up with something along these lines:

class Post
  include Mongoid::Document

  field :hotness, :type => Float, :default => 0
  field :confidence, :type => Float, :default => 0
  field :popularity, :type => Float, :default => 0

  before_save :refresh_hotness

  scope :hottest, desc(:hotness)

  def refresh_hotness

Then you can just grab the ordered, 'hottest' posts with Post.hottest.

share|improve this answer

Your Answer


