Ich möchte diese Frage aus der Perspektive der selbstreferenzierenden Assoziation beantworten, nicht nur aus der Perspektive has_many: through.
Angenommen, wir haben ein CRM mit Kontakten. Kontakte haben Beziehungen zu anderen Kontakten, aber anstatt eine Beziehung zwischen zwei verschiedenen Modellen herzustellen, erstellen wir eine Beziehung zwischen zwei Instanzen desselben Modells. Ein Kontakt kann viele Freunde haben und mit vielen anderen Kontakten befreundet sein, daher müssen wir eine Viele-zu-Viele-Beziehung aufbauen.
Wenn wir ein RDBMS und ActiveRecord verwenden, würden wir has_many: through verwenden. Daher müssten wir ein Join-Modell wie Friendship erstellen. Dieses Modell verfügt über zwei Felder: eine Kontakt-ID, die den aktuellen Kontakt darstellt, der einen Freund hinzufügt, und eine Freund-ID, die den Benutzer darstellt, der befreundet ist.
Aber wir verwenden MongoDB und Mongoid. Wie oben erwähnt, verfügt Mongoid nicht über has_many: through oder eine gleichwertige Funktion. Es wäre mit MongoDB nicht so nützlich, da es keine Join-Abfragen unterstützt. Um eine Viele-Viele-Beziehung in einer Nicht-RDBMS-Datenbank wie MongoDB zu modellieren, verwenden Sie daher ein Feld, das auf beiden Seiten ein Array von 'Fremdschlüsseln' enthält.
class Contact
include Mongoid::Document
has_and_belongs_to_many :practices
end
class Practice
include Mongoid::Document
has_and_belongs_to_many :contacts
end
Wie in der Dokumentation angegeben:
Viele bis viele Beziehungen, in denen die inversen Dokumente in einer vom Basisdokument getrennten Sammlung gespeichert sind, werden mithilfe des Makros has_and_belongs_to_many von Mongoid definiert. Dies zeigt ein ähnliches Verhalten wie Active Record, mit der Ausnahme, dass keine Join-Sammlung erforderlich ist. Die Fremdschlüssel-IDs werden als Arrays auf beiden Seiten der Beziehung gespeichert.
Bei der Definition einer solchen Beziehung wird jedes Dokument in seiner jeweiligen Sammlung gespeichert, und jedes Dokument enthält einen Fremdschlüsselverweis auf das andere in Form eines Arrays.
# the contact document
{
"_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
"practice_ids" : [ ObjectId("4d3ed089fb60ab534684b7f2") ]
}
# the practice document
{
"_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
"contact_ids" : [ ObjectId("4d3ed089fb60ab534684b7f2") ]
}
Für eine selbstreferenzierende Zuordnung in MongoDB haben Sie jetzt einige Optionen.
has_many :related_contacts, :class_name => 'Contact', :inverse_of => :parent_contact
belongs_to :parent_contact, :class_name => 'Contact', :inverse_of => :related_contacts
Was ist der Unterschied zwischen verwandten Kontakten und Kontakten, die viele haben und zu vielen Praktiken gehören? Großer Unterschied! Eine ist eine Beziehung zwischen zwei Entitäten. Andere ist eine Selbstreferenz.