Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement mongoid many-to-many associations?

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?

like image 224
Gavin Avatar asked Jul 26 '10 03:07

Gavin


3 Answers

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

like image 146
PanosJee Avatar answered Oct 07 '22 00:10

PanosJee


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.

like image 35
Gawin Avatar answered Oct 06 '22 22:10

Gawin


this method is deprecated. you can now use references_and_referenced_in_many like so:

class Person
  include Mongoid::Document
  field :name
  references_and referenced_in_many :preferences
end

class Preference
  include Mongoid::Document
  field :name
  references_and referenced_in_many :people
end
like image 31
ian Avatar answered Oct 06 '22 22:10

ian