如何实现的has_many:通过与Mongoid和MongoDB的关系?如何实现、关系、Mongoid、has_many

2023-09-08 15:42:52 作者:染指旳沵唇

使用从 Rails的指导 ,如何做一个模型关系?:使用mongoid的has_many通过协会

的挑战是,mongoid不支持的has_many:通过作为ActiveRecord的确实

 #医生检查出病人
一流的医师LT;的ActiveRecord :: Base的
  的has_many:约会
  的has_many:患者:通过=> :约会
  的has_many:meeting_notes,:通过=> :约会
结束

预约期间拍摄#笔记
类MeetingNote<的ActiveRecord :: Base的
  的has_many:约会
  的has_many:患者:通过=> :约会
  的has_many:医生:通过=> :约会
结束

# 患者
类患者LT;的ActiveRecord :: Base的
  的has_many:约会
  的has_many:医生:通过=> :约会
  的has_many:meeting_notes,:通过=> :约会
结束

# 那次约会
类任命<的ActiveRecord :: Base的
  belongs_to的:医生
  belongs_to的:病人
  belongs_to的:meeting_note
  #有时间戳属性
结束
 

解决方案

Mongoid不具备的has_many:通过或等效的功能。它不会与MongoDB中非常有用,因为它不支持连接查询,所以即使你可以通过另一个引用相关的集合它仍然需要多次查询。

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

通常情况下,如果你在一个RDBMS都有一个多对多的关系,你会使用包含的任何一方外国键阵列的场模型的不同在MongoDB中。例如:

 类医师
  包括Mongoid ::文档
  has_and_belongs_to_many:患者
结束

类病人
  包括Mongoid ::文档
  has_and_belongs_to_many:医生
结束
 

在换句话说,你将消除连接表,它会产生类似的效果,以HAS_MANY:通过访问另一边的条款。但是,你的情况可能是那不恰当的,因为你的连接表是带有一些额外的信息,而不仅仅是联想预约类。

Has Okun s Law Become Invalid in China

您如何模拟这种在很大程度上取决于你需要运行的查询一定程度,但它好像你将需要添加的约会模式,并定义协会病​​人和医生是这样的:

 类医师
  包括Mongoid ::文档
  的has_many:约会
结束

一流的约会
  包括Mongoid ::文档
  belongs_to的:医生
  belongs_to的:病人
结束

类病人
  包括Mongoid ::文档
  的has_many:约会
结束
 

使用MongoDB中关系,你总是不得不作出嵌入或关联的文档之间进行选择。在你的模型我猜MeetingNotes是一个很好的候选人的嵌入式关系。

 类预约
  包括Mongoid ::文档
  embeds_many:meeting_notes
结束

类MeetingNote
  包括Mongoid ::文档
  embedded_in:预约
结束
 

这意味着,你可以预约检索音符就会一起,而你需要多个查询,如果这是一个关联。你必须牢记的16MB大小限制可能开始发挥作用,如果你有一个非常大的一些会议记录的一个文件。

Using this modified example from the Rails guides, how does one model a relational "has_many :through" association using mongoid?

The challenge is that mongoid does not support has_many :through as ActiveRecord does.

# 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

解决方案

Mongoid doesn't have has_many :through or an equivalent feature. It would not be so useful with MongoDB because it does not support join queries so even if you could reference a related collection via another it would still require multiple queries.

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

Normally if you have a many-many relationship in a RDBMS you would model that differently in MongoDB using a field containing an array of 'foreign' keys on either side. For example:

class Physician
  include Mongoid::Document
  has_and_belongs_to_many :patients
end

class Patient
  include Mongoid::Document
  has_and_belongs_to_many :physicians
end

In other words you would eliminate the join table and it would have a similar effect to has_many :through in terms of access to the 'other side'. But in your case thats probably not appropriate because your join table is an Appointment class which carries some extra information, not just the association.

How you model this depends to some extent on the queries that you need to run but it seems as though you will need to add the Appointment model and define associations to Patient and Physician something like this:

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

With relationships in MongoDB you always have to make a choice between embedded or associated documents. In your model I would guess that MeetingNotes are a good candidate for an embedded relationship.

class Appointment
  include Mongoid::Document
  embeds_many :meeting_notes
end

class MeetingNote
  include Mongoid::Document
  embedded_in :appointment
end

This means that you can retrieve the notes together with an appointment all together, whereas you would need multiple queries if this was an association. You just have to bear in mind the 16MB size limit for a single document which might come into play if you have a very large number of meeting notes.