Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Elixir Exto-与3个或更多表关联_Elixir_Phoenix Framework_Ecto - Fatal编程技术网

Elixir Exto-与3个或更多表关联

Elixir Exto-与3个或更多表关联,elixir,phoenix-framework,ecto,Elixir,Phoenix Framework,Ecto,如果我有档案,项目,位置表格,其中: 配置文件有许多位置 项有一个位置 配置文件中的位置和项目不会重叠 我应该如何设计位置表? 以下内容有效吗位置属于两个表 schema "profiles" do ... has_many :location, Location end schema "items" do ... has_one :location, Location end schema "locations" do ...

如果我有
档案
项目
位置
表格,其中:

  • 配置文件
    有许多
    位置
  • 有一个
    位置
  • 配置文件中的
    位置
    项目
    不会重叠
我应该如何设计
位置
表? 以下内容有效吗<代码>位置
属于两个表

schema "profiles" do
...
has_many :location, Location
end

schema "items" do
...
has_one :location, Location
end

schema "locations" do
...
belongs_to :profile, Profile
belongs_to :item, Item
end

还是应该有两个
位置
表?

这是一个非常主观的问题,取决于您将如何使用
位置
表中的数据。这通常是推荐的方法,因为附加的数据库约束会强制在位置记录上始终设置
profile\u id
item\u id
中的一个

defmodule MyApp.Repo.Migrations.CreateLocations do
  use Ecto.Migration

  def change do
    create table(:locations) do
      add :profile_id, references(:profiles, on_delete: :delete_all)
      add :item_id, references(:items, on_delete: :delete_all)
    end

    create constraint(:locations, :at_least_one_ref, check: "profile_id is not null or item_id is not null")
    create index(:locations, [:profile_id, :item_id])
  end
end
然后在变更集中,您可以验证此约束:

def changeset(location, attrs) do 
  location
  |> cast(attrs, [:profile_id, :item_id])
  |> check_constraint(:profile_id, name: :at_least_one_ref)
end

另一种方法非常特定于Ecto,但效果非常好,特别是因为您提到概要文件和项目之间没有位置重叠,使用和使用嵌入式关联。如果您使用的是Postgres,如果需要,您甚至应该能够在JSONB列上创建索引。

这是一个非常主观的问题,取决于您将如何使用
位置
表中的数据。这通常是推荐的方法,因为附加的数据库约束会强制在位置记录上始终设置
profile\u id
item\u id
中的一个

defmodule MyApp.Repo.Migrations.CreateLocations do
  use Ecto.Migration

  def change do
    create table(:locations) do
      add :profile_id, references(:profiles, on_delete: :delete_all)
      add :item_id, references(:items, on_delete: :delete_all)
    end

    create constraint(:locations, :at_least_one_ref, check: "profile_id is not null or item_id is not null")
    create index(:locations, [:profile_id, :item_id])
  end
end
然后在变更集中,您可以验证此约束:

def changeset(location, attrs) do 
  location
  |> cast(attrs, [:profile_id, :item_id])
  |> check_constraint(:profile_id, name: :at_least_one_ref)
end

另一种方法非常特定于Ecto,但效果非常好,特别是因为您提到概要文件和项目之间没有位置重叠,使用和使用嵌入式关联。如果您使用的是Postgres,如果需要,您甚至应该能够在JSONB列上创建索引。

我发现首先考虑表要容易得多。代码中的抽象(如EXTO或ORM)只有在使您的数据交互工作更容易时才有用。我不确定我是否遵循了您所说的“
profile
中的
location
item
不会重叠”的意思,但我没有遵循profile和items之间的关系。在定义模式中的所有关系时,你不会得到额外的分数:我建议从你需要的查询开始,例如“一个位置上所有项目的列表”,并建立所需的关系来实现它们。我发现首先考虑表要容易得多。代码中的抽象(如EXTO或ORM)只有在使您的数据交互工作更容易时才有用。我不确定我是否遵循了您所说的“
profile
中的
location
item
不会重叠”的意思,但我没有遵循profile和items之间的关系。在定义模式中的所有关系时,你不会得到额外的分数:我建议从你需要的查询开始,例如“一个位置上所有项目的列表”,并建立所需的关系来实现它们。实际上,这就是我现在正在做的。不管怎样,谢谢你的回答。实际上这就是我现在正在做的。无论如何,谢谢你的回答。