I currently have the following controller method in a Rails app:
def index
@entries = []
@entries << QuickPost.where(:user_id.in => current_user.followees.map(&:ff_id) << current_user.id)
@entries << Infographic.where(:user_id.in => current_user.followees.map(&:ff_id) << current_user.id)
@entries.flatten!.sort!{ |a,b| b.created_at <=> a.created_at }
@entries = Kaminari.paginate_array(@entries).page(params[:page]).per(10)
end
I realise this is terribly inefficient so I’m looking for a better way to achieve the same goal but I’m new to MongoDB and wondering what the best solution would be.
Is there a way to make a sorted limit() query or a MapReduce function in MongoDB across two collections? I’m guessing there isn’t but it would certainly save a lot of effort in this case!
I’m currently thinking I have two options:
- Create a master ‘StreamEntry’ type model and have both Infographic and QuickPost inherit from that so that both data types are stored on the same collection. The issue with this is that I have existing data and I don’t know how to move it from the old collections to the new.
- Create a separate Stream/ActivityStream model using something like Streama (https://github.com/christospappas/streama). The issues I can see here is that it would require a fair bit of upfront work and due to privacy settings and editing/removal of items the stream would need to be rebuilt often.
Are there options I have overlooked? Am I over-engineering with the above options? What sort of best practices are there for this type of situation?
Any info would be greatly appreciated, I’m really liking MongoDB so far and want to avoid falling into pitfalls like this in the future. Thanks.
The inherit solution is fine, but when the inherited models are close.
For example :
But when the models grows, or are too different, your second solution is better.
and for example :
The dependant destroy make the activity destroyed when the QuickPost is destroyed. You can use has_many and adapt.
And to create the activities, you can create an observer :