I want to port a social network to Mongoid. The join table between friends is very large. Is there any way for Mongoid to handle this join table out of the box? I've seen a couple of in-model roll-your-own solutions to it, but nothing the looks efficient. Is there a way to handle this? Or is this a case where I shouldn't be using Mongoid?
You don't do many to many relationships and join tables with MongoDB. Each user would have their entire friend graph stored on the actual user object, along with everything else like preferences, pictures(GridFS), etc. If you need to do special stuff that requires relational algebra, just use an RDBMS, otherwise MongoDB will work well. It's possible to do advanced queries, but you must use mapreduce.
Many-to-many should be avoid for scale applications. What Twitter for example does is that it store the followers ids in comma seperated format (string) inside the user object. Using MongoDB is even better as it supports arrays.
Remember that what describes best NoSQL is the term NoJoin ;-)
You can create many-to-many (polymorphic) associations by using relational associations and store the relation as an array.
class Person
include Mongoid::Document
field :name
references_many :preferences, :stored_as => :array, :inverse_of => :people
end
class Preference
include Mongoid::Document
field :name
references_many :people, :stored_as => :array, :inverse_of => :preferences
end
ps1 = Person.create(:name => 'John Doe')
pf1 = Preference.create(:name => 'Preference A')
pf2 = Preference.create(:name => 'Preference B')
ps1.preferences << pf1
ps1.preferences << pf2
ps1.save
pf1.people.each {|ps| puts ps.name }
ps1.preferences.each {|pf| puts pf.name }
More about relational associations can be found in the Mongoid documentation: http://mongoid.org/docs/associations/
Note: references_many stored as arrays can be staggering slow on mass creating/updating objects with many relations. A more traditional RDBMS will easily outperform Mongo because it will add a new row for each relation, where mongo needs to retrieve and update the object_ids array for the object itself and for each relation.