elixir - Ecto(Phoenix)中的外键数组
问题描述
我是网络开发的初学者,所以请原谅我缺乏知识。
我有一个Teacher
和一个Student
Ecto 模式。它们应该Class
通过遵循以下规则调用的另一个模式链接:
每个班只有一个老师,有很多学生。
每个老师都可以参加许多班级
每个学生都可以成为许多班级的一部分。
这是我到目前为止构建的架构:
# Part of student.ex
schema "students" do
field :active, :boolean, default: false
field :birthday, :date
field :email, :string, unique: true
field :firstname, :string
field :lastname, :string
field :phone, :string, unique: true
belongs_to :classes, Class, foreign_key: :class_id
many_to_many :teachers, Users.Teacher, join_through: "classes"
timestamps()
end
# Part of teacher.ex
schema "teachers" do
field :active, :boolean, default: false
field :birthday, :date
field :email, :string, unique: true
field :firstname, :string
field :lastname, :string
field :phone, :string, unique: true
belongs_to :classes, Class, foreign_key: :class_id
many_to_many :students, Users.Student, join_through: "classes"
timestamps()
end
# Part of class.ex
schema "classes" do
field :end_date, :date
field :time, :time
field :level, :string
field :start_date, :date
field :title, :string
has_many :students, Users.Student
has_one :teacher, Users.Teacher
embeds_many :sessions, Session
timestamps()
end
这里看起来还不错。但问题是,如何在迁移文件中指定“学生 ID 数组”?以下是迁移功能:
# Part of students migration file. It's the same for teachers.
def change do
create table(:students) do
add :firstname, :string, null: false, size: 32
add :lastname, :string, null: false, size: 32
add :phone, :string, null: false, size: 16
add :email, :string, size: 32
add :birthday, :date
add :active, :boolean, default: false, null: false
timestamps()
end
create(unique_index(:students, [:phone]))
end
这是我现在真正陷入困境的地方:
def change do
create table(:classes) do
add :title, :string, null: false
add :level, :string
add :hours, :string, null: false
add :start_date, :date
add :end_date, :date
add :teacher_id, references(:teachers), primary_key: true
# HERE! How do I create a column for an array of student_id foreign keys?
timestamps()
end
create(index(:classes, [:teacher_id]))
end
提前致谢。
解决方案
正如文档中所述Ecto.Schema.belongs_to/3
您应该
belongs_to
在包含外键的表中使用。想象一段company <-> employee
关系。如果在基础数据库表中employee
包含,我们说属于。事实上,当您调用此宏时,会在架构中自动为您定义一个名为外键的字段。company_id
employee
company
相反,既不Ecto.Schema.has_one/3
也不Ecto.Schema.has_many/3
暗示各自领域的存在。一切都在此链接的另一端完成。
也就是说,
students
架构应该有class_id
字段(已经在那里)classes
可能应该有teacher_id
(假设老师可能有几个班级。)要做到这一点,请更改teachers
为has_many :classes
而不是belongs_to :class
和更改classes
为belongs_to :teacher
而不是has_one :teacher
。
无论您是否希望学生属于多个班级,架构都是不正确的。class_id
每个记录中外键的存在students
意味着每个学生都有这个特定的类相关联。你应该删除
belongs_to :classes, Class, foreign_key: :class_id
从students
,因为它首先将一个学生固定在一个班级。然后你必须引入classes_to_students
连接模式,如此处所述Ecto.Schema.many_to_many/3
。
推荐阅读
- python - 防止关闭 Python Tkinter 窗口(包括 Alt+F4)
- ios - 如何继续在 Apple Watch 上收集运动传感器数据?
- shell - while循环脚本在满足条件时重试并结束
- apache-spark - 如何将实体主键映射到 Spark ML 预测?
- c++ - 一起使用 std::thread 和 CUDA
- javascript - 过滤后的数组长度
- javascript - 可以向 angular cli 生成的脚本标签添加跨域属性吗?
- c# - 将刚体添加到对象 Unity3D 时出现问题
- python - 在一次热编码期间/之后,是否可以使用另一列的值而不是二进制标志?
- python - 添加第二个 LSTM 层时遇到问题“输入 0 与层 lstm_2 不兼容:预期 ndim=3,发现 ndim=2”