Tôi muốn trả lời câu hỏi này từ quan điểm liên kết tự tham chiếu, không chỉ theo quan điểm has_many: thông qua.
Giả sử chúng tôi có một CRM với các địa chỉ liên hệ. Địa chỉ liên hệ sẽ có mối quan hệ với các địa chỉ liên hệ khác, nhưng thay vì tạo mối quan hệ giữa hai mô hình khác nhau, chúng tôi sẽ tạo mối quan hệ giữa hai phiên bản của cùng một mô hình. Một liên hệ có thể có nhiều bạn bè và kết bạn với nhiều liên hệ khác, vì vậy chúng ta sẽ phải tạo ra một mối quan hệ nhiều-nhiều.
Nếu chúng ta đang sử dụng RDBMS và ActiveRecord, chúng ta sẽ sử dụng has_many: through. Vì vậy, chúng ta sẽ cần tạo một mô hình tham gia, như Friendship. Mô hình này sẽ có hai trường, contact_id đại diện cho người liên hệ hiện tại đang thêm bạn và friend_id đại diện cho người dùng đang được kết bạn.
Nhưng chúng tôi đang sử dụng MongoDB và Mongoid. Như đã nêu ở trên, Mongoid không có has_many: through hoặc một tính năng tương đương. Nó sẽ không hữu ích với MongoDB vì nó không hỗ trợ các truy vấn nối. Do đó, để mô hình hóa mối quan hệ nhiều-nhiều trong cơ sở dữ liệu không phải RDBMS như MongoDB, bạn sử dụng một trường chứa một mảng các khóa 'ngoại' ở hai bên.
class Contact
include Mongoid::Document
has_and_belongs_to_many :practices
end
class Practice
include Mongoid::Document
has_and_belongs_to_many :contacts
end
Như tài liệu nói:
Mối quan hệ nhiều đến nhiều trong đó các tài liệu nghịch đảo được lưu trữ trong một bộ sưu tập riêng biệt từ tài liệu cơ sở được xác định bằng cách sử dụng macro has_and_belongs_to_many của Mongoid. Điều này thể hiện hành vi tương tự như Active Record với ngoại lệ là không cần tập hợp nối, id khóa ngoại được lưu trữ dưới dạng mảng ở hai bên của quan hệ.
Khi xác định một quan hệ có tính chất này, mỗi tài liệu được lưu trữ trong bộ sưu tập tương ứng của nó và mỗi tài liệu chứa một tham chiếu “khóa ngoại” đến tài liệu kia dưới dạng một mảng.
# the contact document
{
"_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
"practice_ids" : [ ObjectId("4d3ed089fb60ab534684b7f2") ]
}
# the practice document
{
"_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
"contact_ids" : [ ObjectId("4d3ed089fb60ab534684b7f2") ]
}
Bây giờ đối với một Hiệp hội tự tham chiếu trong MongoDB, bạn có một vài lựa chọn.
has_many :related_contacts, :class_name => 'Contact', :inverse_of => :parent_contact
belongs_to :parent_contact, :class_name => 'Contact', :inverse_of => :related_contacts
Sự khác biệt giữa các liên hệ có liên quan và liên hệ có nhiều và thuộc nhiều thực hành là gì? Sự khác biệt lớn! Một là mối quan hệ giữa hai thực thể. Khác là tự tham khảo.