views:

405

answers:

3

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?

A: 

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.

Preston Marshall
We only need to store the user's friend IDs as an array on the user object, right? Does mongoid have methods to deal with this? Or do I need to write them myself?
Gavin
A: 

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 ;-)

PanosJee
+1  A: 

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.

gawin
In response to "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": yes, such a choice can be slow. If that is a problem you could create a "joining" collection as well, if you like. Just use your application for the join.
David James