put_assoc 抱怨类型错误
put_assoc complains of wrong type
我有表示有向图的 Ecto 模式 -- 有一个 Node
模式,通过中间 NodeEdge
模式具有自引用多对多关系。即
schema "nodes" do
field :name, :string
many_to_many :edges, MyApp.Node,
join_through: MyApp.NodeEdge,
join_keys: [source: :id, target: :id]
timestamps()
end
schema "node_edges" do
belongs_to :source, MyApp.Node
belongs_to :target, MyApp.Node
timestamps()
end
具有以下初始迁移:
create table(:nodes) do
add :name, :string, null: false
timestamps()
end
create table(:node_edges) do
add :source, references(:nodes)
add :target, references(:nodes)
timestamps()
end
我正在尝试像这样批量插入边缘:
now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
new_edges =
Enum.map(
result.edges,
&%NodeEdge{
source: curr_name,
target: &1,
inserted_at: now,
updated_at: now
}
)
node
|> Repo.preload(:edges)
|> Ecto.Changeset.change()
|> Ecto.Changeset.put_assoc(:edges, my_edges)
|> Repo.update!()
据我所知,这与 put_assoc/4
的文档非常接近。但是,我收到一个错误:
** (ArgumentError) expected changeset data to be a Elixir.MyApp.Node struct, got: %MyApp.NodeEdge{__meta__: #Ecto.Schema.Metadata<:built, "node_edges">, id: nil, inserted_at: ~N[2019-06-25 23:18:35], source: "nodeA", source_id: nil, target: "nodeB", target_id: nil, updated_at: ~N[2019-06-25 23:18:35]}
是不是我事先不知道节点的ID?或者谁能看到另一个问题?
Ab 错误很严重 self-explained:您正在创建 NodeEdge
的列表,然后尝试将此列表应用于关联 edges
,即 Node
类型。
一组解决方案:
构建 Node
列表,而不是 NodeEdge
列表。将此列表与 put_assoc
添加与节点边的关系
schema "nodes" do
field :name, :string
many_to_many :edges, MyApp.Node,
join_through: MyApp.NodeEdge,
join_keys: [source: :id, target: :id]
has_many :node_edges, MyApp.NodeEdge, foreign_key: source
timestamps()
end
现在,将您的 NodeEdge
列表放在这里。
只需创建此列表 - 绝对是 self-explained。因为 NodeEdge
有关系 - 使用它们来建立关联:
%NodeEdge{
source: put_assoc(:source, curr_name),
target: put_assoc(:target, &1),
inserted_at: now,
updated_at: now
}
构建此列表然后保存。
我有表示有向图的 Ecto 模式 -- 有一个 Node
模式,通过中间 NodeEdge
模式具有自引用多对多关系。即
schema "nodes" do
field :name, :string
many_to_many :edges, MyApp.Node,
join_through: MyApp.NodeEdge,
join_keys: [source: :id, target: :id]
timestamps()
end
schema "node_edges" do
belongs_to :source, MyApp.Node
belongs_to :target, MyApp.Node
timestamps()
end
具有以下初始迁移:
create table(:nodes) do
add :name, :string, null: false
timestamps()
end
create table(:node_edges) do
add :source, references(:nodes)
add :target, references(:nodes)
timestamps()
end
我正在尝试像这样批量插入边缘:
now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
new_edges =
Enum.map(
result.edges,
&%NodeEdge{
source: curr_name,
target: &1,
inserted_at: now,
updated_at: now
}
)
node
|> Repo.preload(:edges)
|> Ecto.Changeset.change()
|> Ecto.Changeset.put_assoc(:edges, my_edges)
|> Repo.update!()
据我所知,这与 put_assoc/4
的文档非常接近。但是,我收到一个错误:
** (ArgumentError) expected changeset data to be a Elixir.MyApp.Node struct, got: %MyApp.NodeEdge{__meta__: #Ecto.Schema.Metadata<:built, "node_edges">, id: nil, inserted_at: ~N[2019-06-25 23:18:35], source: "nodeA", source_id: nil, target: "nodeB", target_id: nil, updated_at: ~N[2019-06-25 23:18:35]}
是不是我事先不知道节点的ID?或者谁能看到另一个问题?
Ab 错误很严重 self-explained:您正在创建 NodeEdge
的列表,然后尝试将此列表应用于关联 edges
,即 Node
类型。
一组解决方案:
构建
Node
列表,而不是NodeEdge
列表。将此列表与put_assoc
添加与节点边的关系
schema "nodes" do field :name, :string many_to_many :edges, MyApp.Node, join_through: MyApp.NodeEdge, join_keys: [source: :id, target: :id] has_many :node_edges, MyApp.NodeEdge, foreign_key: source timestamps() end
现在,将您的
NodeEdge
列表放在这里。只需创建此列表 - 绝对是 self-explained。因为
NodeEdge
有关系 - 使用它们来建立关联:%NodeEdge{ source: put_assoc(:source, curr_name), target: put_assoc(:target, &1), inserted_at: now, updated_at: now }
构建此列表然后保存。