ฉันต้องการตอบคำถามนี้จากมุมมองของการเชื่อมโยงการอ้างอิงตนเองไม่ใช่แค่ has_many: ผ่านมุมมอง
สมมติว่าเรามี CRM กับผู้ติดต่อ ผู้ติดต่อจะมีความสัมพันธ์กับผู้ติดต่ออื่น ๆ แต่แทนที่จะสร้างความสัมพันธ์ระหว่างโมเดลที่แตกต่างกันสองแบบเราจะสร้างความสัมพันธ์ระหว่างสองอินสแตนซ์ของโมเดลเดียวกัน ผู้ติดต่อสามารถมีเพื่อนมากมายและถูกผูกมิตรกับผู้ติดต่ออื่น ๆ อีกมากมายดังนั้นเราจะต้องสร้างความสัมพันธ์แบบกลุ่มต่อกลุ่ม
หากเราใช้ RDBMS และ ActiveRecord เราจะใช้ has_many: through ดังนั้นเราจะต้องสร้างรูปแบบการเข้าร่วมเช่นมิตรภาพ โมเดลนี้จะมีสองฟิลด์ contact_id ที่แสดงถึงผู้ติดต่อปัจจุบันที่กำลังเพิ่มเพื่อนและ friend_id ที่แสดงถึงผู้ใช้ที่กำลังเป็นเพื่อนกัน
แต่เราใช้ MongoDB และ Mongoid ตามที่ระบุไว้ข้างต้น Mongoid ไม่มี has_many: through หรือคุณสมบัติที่เทียบเท่า มันจะไม่มีประโยชน์กับ MongoDB เพราะมันไม่รองรับการสืบค้นการเข้าร่วม ดังนั้นในการสร้างแบบจำลองความสัมพันธ์แบบหลายกลุ่มในฐานข้อมูลที่ไม่ใช่ RDBMS เช่น MongoDB คุณต้องใช้ฟิลด์ที่มีอาร์เรย์ของคีย์ "ต่างประเทศ" ที่ด้านใดด้านหนึ่ง
class Contact
include Mongoid::Document
has_and_belongs_to_many :practices
end
class Practice
include Mongoid::Document
has_and_belongs_to_many :contacts
end
ตามเอกสารระบุ:
ความสัมพันธ์แบบมากถึงหลายความสัมพันธ์ที่เอกสารผกผันถูกเก็บไว้ในคอลเลกชันที่แยกต่างหากจากเอกสารพื้นฐานถูกกำหนดโดยใช้มาโคร has_and_belongs_to_many ของ Mongoid สิ่งนี้แสดงลักษณะการทำงานที่คล้ายกันกับ Active Record โดยมีข้อยกเว้นว่าไม่จำเป็นต้องมีการรวมคอลเลกชันรหัสคีย์ต่างประเทศจะถูกจัดเก็บเป็นอาร์เรย์ที่ด้านใดด้านหนึ่งของความสัมพันธ์
เมื่อกำหนดความสัมพันธ์ในลักษณะนี้เอกสารแต่ละชุดจะถูกเก็บไว้ในคอลเลคชันตามลำดับและเอกสารแต่ละชุดจะมีการอ้างอิง "คีย์ต่างประเทศ" ไปยังอีกชุดหนึ่งในรูปแบบของอาร์เรย์
# the contact document
{
"_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
"practice_ids" : [ ObjectId("4d3ed089fb60ab534684b7f2") ]
}
# the practice document
{
"_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
"contact_ids" : [ ObjectId("4d3ed089fb60ab534684b7f2") ]
}
ตอนนี้สำหรับสมาคมการอ้างอิงตนเองใน MongoDB คุณมีทางเลือกไม่กี่ทาง
has_many :related_contacts, :class_name => 'Contact', :inverse_of => :parent_contact
belongs_to :parent_contact, :class_name => 'Contact', :inverse_of => :related_contacts
อะไรคือความแตกต่างระหว่างผู้ติดต่อที่เกี่ยวข้องและผู้ติดต่อที่มีหลายคนและอยู่ในแนวทางปฏิบัติมากมาย? แตกต่างกันมาก! หนึ่งคือความสัมพันธ์ระหว่างสองเอนทิตี อื่น ๆ คือการอ้างอิงตัวเอง