Has_many को कैसे लागू किया जाए: Mongoid और mongodb के साथ संबंधों के माध्यम से?


96

रेल गाइड से इस संशोधित उदाहरण का उपयोग करते हुए , कैसे एक मॉडल एक संबंधपरक "has_many: mongoid का उपयोग करके" एसोसिएशन के माध्यम से करता है?

चुनौती यह है कि mongoid has_many का समर्थन नहीं करता है: के माध्यम से ActiveRecord करता है।

# doctor checking out patient
class Physician < ActiveRecord::Base
  has_many :appointments
  has_many :patients, :through => :appointments
  has_many :meeting_notes, :through => :appointments
end

# notes taken during the appointment
class MeetingNote < ActiveRecord::Base
  has_many :appointments
  has_many :patients, :through => :appointments
  has_many :physicians, :through => :appointments
end

# the patient
class Patient < ActiveRecord::Base
  has_many :appointments
  has_many :physicians, :through => :appointments
  has_many :meeting_notes, :through => :appointments
end

# the appointment
class Appointment < ActiveRecord::Base
  belongs_to :physician
  belongs_to :patient
  belongs_to :meeting_note
  # has timestamp attribute
end

जवाबों:


151

Mongoid has_many नहीं है: के माध्यम से या एक बराबर सुविधा। यह MongoDB के साथ इतना उपयोगी नहीं होगा क्योंकि यह प्रश्नों में शामिल होने का समर्थन नहीं करता है, भले ही आप किसी अन्य के माध्यम से संबंधित संग्रह को संदर्भित कर सकते हों, फिर भी इसे कई प्रश्नों की आवश्यकता होगी।

https://github.com/mongoid/mongoid/issues/544

आम तौर पर अगर आपके पास RDBMS में कई-कई संबंध हैं, तो आप अलग-अलग तरह से MongoDB में किसी भी क्षेत्र में 'विदेशी' कुंजियों की एक सरणी का उपयोग करके मॉडल बना सकते हैं। उदाहरण के लिए:

class Physician
  include Mongoid::Document
  has_and_belongs_to_many :patients
end

class Patient
  include Mongoid::Document
  has_and_belongs_to_many :physicians
end

दूसरे शब्दों में आप ज्वाइन टेबल को खत्म कर देंगे और इसका'_साइड साइड 'तक पहुंच के संदर्भ में has_many के समान प्रभाव पड़ेगा। लेकिन आपके मामले में संभवत: यह उचित नहीं है क्योंकि आपकी ज्वाइन टेबल एक अप्वाइंटमेंट क्लास है, जो सिर्फ एसोसिएशन ही नहीं, कुछ अतिरिक्त जानकारी भी देती है।

आप किस प्रकार मॉडल करते हैं, यह कुछ हद तक उन प्रश्नों पर निर्भर करता है, जिन्हें आपको चलाने की आवश्यकता है, लेकिन ऐसा लगता है जैसे आपको अपॉइंटमेंट मॉडल को जोड़ना होगा और रोगी और चिकित्सक को संघों को इस तरह परिभाषित करना होगा:

class Physician
  include Mongoid::Document
  has_many :appointments
end

class Appointment
  include Mongoid::Document
  belongs_to :physician
  belongs_to :patient
end

class Patient
  include Mongoid::Document
  has_many :appointments
end

MongoDB में रिश्तों के साथ आपको हमेशा एम्बेडेड या संबंधित दस्तावेजों के बीच चयन करना होगा। आपके मॉडल में मुझे लगता है कि मीटिंगनाटेड एक अंतर्निहित रिश्ते के लिए एक अच्छा उम्मीदवार है।

class Appointment
  include Mongoid::Document
  embeds_many :meeting_notes
end

class MeetingNote
  include Mongoid::Document
  embedded_in :appointment
end

इसका मतलब है कि आप सभी को एक साथ एक नियुक्ति के साथ नोटों को पुनः प्राप्त कर सकते हैं, जबकि यदि यह एक संघ था तो आपको कई प्रश्नों की आवश्यकता होगी। आपको एक ही दस्तावेज़ के लिए 16MB आकार की सीमा को ध्यान में रखना होगा जो कि बहुत बड़ी संख्या में मीटिंग नोट्स के होने पर खेल में आ सकता है।


7
+1 बहुत अच्छा जवाब, सिर्फ जानकारी के लिए, मोंगोडब आकार सीमा 16 एमबी तक बढ़ा दी गई है।
रगड़

1
जिज्ञासा से बाहर (देर से पूछताछ के लिए खेद है), मैं मोंगॉयड के लिए भी नया हूं और मैं सोच रहा था कि जब आप एसोसिएशन को संग्रहीत करने के लिए एक अलग संग्रह का उपयोग करके nn संबंध बनाते हैं तो आप डेटा के लिए कैसे क्वेरी करेंगे, क्या यह वैसा ही था जैसा वह था ActiveRecord के साथ?
मासूम

38

बस इस पर विस्तार करने के लिए, यहां उन विधियों के साथ विस्तारित मॉडल हैं जो has_many के समान कार्य करते हैं: ActiveRecord के माध्यम से रिकॉर्ड सरणी के बजाय क्वेरी प्रॉक्सी वापस करके:

class Physician
  include Mongoid::Document
  has_many :appointments

  def patients
    Patient.in(id: appointments.pluck(:patient_id))
  end
end

class Appointment
  include Mongoid::Document
  belongs_to :physician
  belongs_to :patient
end

class Patient
  include Mongoid::Document
  has_many :appointments

  def physicians
    Physician.in(id: appointments.pluck(:physician_id))
  end
end

2
यह निश्चित रूप से मदद करने के लिए मेरी विधि को पुनः प्राप्त करने के लिए एक सरणी लौटा रहा था जिसने पृष्ठन को गड़बड़ कर दिया था।
prasad.surase

1
कोई जादू नहीं। @CyrilDD, आप किस बारे में बात कर रहे हैं? नक्शा (&: Phys_id) मानचित्र के लिए छोटा है {| नियुक्ति | नियुक्ति
.physician.id

मुझे आश्चर्य है, क्या यह दृष्टिकोण 16MBs दस्तावेज़ आकार सीमा के साथ संभावित निराशा को कम करता है, यह देखते हुए कि दस्तावेज़ एम्बेडेड नहीं हैं, बल्कि एक बाहरी मॉडल का उपयोग करने से जुड़े हैं? (क्षमा करें, यदि यह एक
नॉब

जैसा कि फ्रांसिस बताते हैं, का उपयोग कर के .pluck()sinstead .mapहै MUCH तेजी से। क्या आप भविष्य के पाठकों के लिए अपना जवाब अपडेट कर सकते हैं?
सिरिल डचोन-डोरिस

मैं मिल रहा हूंundefined method 'pluck' for #<Array:...>
व्यिलियम जुड

7

स्टीवन सोरोका समाधान वास्तव में बहुत अच्छा है! मेरे पास जवाब देने के लिए प्रतिष्ठा नहीं है (इसीलिए मैं एक नया उत्तर जोड़ रहा हूं: P) लेकिन मुझे लगता है कि एक रिश्ते के लिए मानचित्र का उपयोग करना महंगा है (विशेषकर यदि आपके has_many संबंध में हंडर्स हैं। हजारों रिकॉर्ड) क्योंकि यह हो जाता है डेटाबेस से डेटा, प्रत्येक रिकॉर्ड का निर्माण, मूल सरणी उत्पन्न करता है और फिर दिए गए ब्लॉक से मूल्यों के साथ एक नया निर्माण करने के लिए मूल सरणी पर पुनरावृत्त करता है।

प्लक का उपयोग तेज और शायद सबसे तेज विकल्प है।

class Physician
  include Mongoid::Document
  has_many :appointments

  def patients
    Patient.in(id: appointments.pluck(:patient_id))
  end
end

class Appointment
  include Mongoid::Document
  belongs_to :physician
  belongs_to :patient 
end

class Patient
  include Mongoid::Document
  has_many :appointments 

  def physicians
    Physician.in(id: appointments.pluck(:physician_id))
  end
end

यहाँ बेंचमार्क.मैं के साथ कुछ आँकड़े:

> Benchmark.measure { physician.appointments.map(&:patient_id) }
 => #<Benchmark::Tms:0xb671654 @label="", @real=0.114643818, @cstime=0.0, @cutime=0.0, @stime=0.010000000000000009, @utime=0.06999999999999984, @total=0.07999999999999985> 

> Benchmark.measure { physician.appointments.pluck(:patient_id) }
 => #<Benchmark::Tms:0xb6f4054 @label="", @real=0.033517774, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.0, @total=0.0> 

मैं सिर्फ 250 नियुक्तियों का उपयोग कर रहा हूं। अपॉइंटमेंट डॉक्यूमेंट में:

मुझे आशा है कि यह मदद करता है, पढ़ने के लिए धन्यवाद!


मैं मिल रहा हूंundefined method 'pluck' for #<Array:...>
व्यिलियम जुड

0

मैं इस प्रश्न का उत्तर स्वयं-संदर्भ संघ के दृष्टिकोण से देना चाहता हूं, न कि has_many: परिप्रेक्ष्य के माध्यम से।

मान लीजिए कि हमारे पास संपर्कों के साथ एक सीआरएम है। संपर्कों के अन्य संपर्कों के साथ संबंध होंगे, लेकिन हम दो अलग-अलग मॉडलों के बीच संबंध बनाने के बजाय, हम एक ही मॉडल के दो उदाहरणों के बीच संबंध बना रहे होंगे। एक संपर्क में कई दोस्त हो सकते हैं और कई अन्य संपर्कों से दोस्ती की जा सकती है, इसलिए हमें कई-कई रिश्ते बनाने होंगे।

यदि हम RDBMS और ActiveRecord का उपयोग कर रहे हैं, तो हम has_many का उपयोग करेंगे: के माध्यम से। इस प्रकार हमे फ्रेंडशिप की तरह एक जॉइन मॉडल बनाना होगा। इस मॉडल में दो फ़ील्ड होंगे, एक contact_id जो वर्तमान संपर्क का प्रतिनिधित्व करता है जो एक मित्र और एक मित्र को जोड़ रहा है_ जो उस उपयोगकर्ता का प्रतिनिधित्व करता है जो मित्रवत हो रहा है।

लेकिन हम MongoDB और Mongoid का उपयोग कर रहे हैं। जैसा कि ऊपर कहा गया है, Mongoid has_many नहीं है: के माध्यम से या एक बराबर सुविधा। यह MongoDB के साथ इतना उपयोगी नहीं होगा क्योंकि यह प्रश्नों में शामिल होने का समर्थन नहीं करता है। इसलिए, MongoDB जैसे गैर-RDBMS डेटाबेस में कई-कई संबंधों को मॉडल करने के लिए, आप दोनों तरफ 'विदेशी' कुंजियों के एक सरणी वाले फ़ील्ड का उपयोग करते हैं।

class Contact
  include Mongoid::Document
  has_and_belongs_to_many :practices
end

class Practice
  include Mongoid::Document
  has_and_belongs_to_many :contacts
end

जैसा कि प्रलेखन में कहा गया है:

कई रिश्तों में जहां उलटे दस्तावेज़ों को आधार दस्तावेज़ से एक अलग संग्रह में संग्रहीत किया जाता है, उन्हें Mongoid's has_and_belongs_to_many मैक्रो का उपयोग करके परिभाषित किया गया है। यह सक्रिय रिकॉर्ड के समान व्यवहार को इस अपवाद के साथ प्रदर्शित करता है कि किसी भी सम्मिलित संग्रह की आवश्यकता नहीं है, विदेशी कुंजी आईडी को संबंध के दोनों ओर सरणियों के रूप में संग्रहीत किया जाता है।

इस प्रकृति के संबंध को परिभाषित करते समय, प्रत्येक दस्तावेज़ को अपने संबंधित संग्रह में संग्रहीत किया जाता है, और प्रत्येक दस्तावेज़ में एक सरणी के रूप में दूसरे के लिए "विदेशी कुंजी" संदर्भ होता है।

# 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

संबंधित संपर्क और संपर्क कई होने और कई प्रथाओं से संबंधित होने के बीच क्या अंतर है? बड़ा अंतर! एक दो संस्थाओं के बीच एक संबंध है। अन्य एक आत्म-संदर्भ है।


उदाहरण के दस्तावेज समान प्रतीत होते हैं?
साइबर मेव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.