Ecto, Phoenix:如何使用 embeds_many 声明更新模型?
Ecto, Phoenix: How to update a model with an embeds_many declaration?
我有两个模型,Owner
和 Property
,其中 Owner
的架构有一个 embeds_many
声明,如下所示:
defmodule MyApp.Owner do
use MyApp.Web, :model
alias MyApp.Property
schema "owners" do
field name, :string
embeds_many :properties, Property
timestamps()
end
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \ %{}) do
struct
|> cast(params, [])
|> validate_required([])
end
end
还有这个:
defmodule MyApp.Property do
use MyApp.Web, :model
embedded_schema do
field :name, :string
field :value, :float, default: 0
end
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:name, :value])
|> validate_required([:name])
end
end
我使用的migration是:
defmodule MyApp.Repo.Migrations.CreateOwner do
use Ecto.Migration
def down do
drop table(:owners)
end
def change do
drop_if_exists table(:owners)
create table(:owners) do
add :name, :string
add :properties, :map
timestamps()
end
end
end
一个可能的seed是:
alias MyApp.{Repo, Owner, Property}
Repo.insert!(%Owner{
name: "John Doe",
properties: [
%Property{
name: "Property A"
},
%Property{
name: "Property B",
value: 100000
},
%Property{
name: "Property C",
value: 200000
}
]
})
最后,我的问题是:如何将 John Doe
的 Property C
的值从 200000
更新为 300000
?如果 John Doe
买了一个 Property D
:
%Property{
name: "Property D"
value: 400000
}
如何将其添加到他的 properties
数据库中? (我正在使用 Postgres)。
最简单的方法是获取记录,更新 properties
列出并保存更改:
owner = Repo.get!(Owner, 1)
properties = owner.properties
# update all properties with name "Property C"'s value to 400000
properties = for %Property{name: name} = property <- properties do
if name == "Property C" do
%{property | value: 400000}
else
property
end
end
# add a property to the start
properties = [%Property{name: "Property D", value: 400000} | properties]
# or to the end
# properties = properties ++ [%Property{name: "Property D", value: 400000}]
# update
Owner.changeset(owner, %{properties: properties})
|> Repo.update!
你可以使用JSON函数做一些操作(至少插入一个属性)
由 PostgreSQL 使用提供
fragment
但我认为您无法搜索和有条件地更新项目
使用它们的数组。
我有两个模型,Owner
和 Property
,其中 Owner
的架构有一个 embeds_many
声明,如下所示:
defmodule MyApp.Owner do
use MyApp.Web, :model
alias MyApp.Property
schema "owners" do
field name, :string
embeds_many :properties, Property
timestamps()
end
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \ %{}) do
struct
|> cast(params, [])
|> validate_required([])
end
end
还有这个:
defmodule MyApp.Property do
use MyApp.Web, :model
embedded_schema do
field :name, :string
field :value, :float, default: 0
end
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:name, :value])
|> validate_required([:name])
end
end
我使用的migration是:
defmodule MyApp.Repo.Migrations.CreateOwner do
use Ecto.Migration
def down do
drop table(:owners)
end
def change do
drop_if_exists table(:owners)
create table(:owners) do
add :name, :string
add :properties, :map
timestamps()
end
end
end
一个可能的seed是:
alias MyApp.{Repo, Owner, Property}
Repo.insert!(%Owner{
name: "John Doe",
properties: [
%Property{
name: "Property A"
},
%Property{
name: "Property B",
value: 100000
},
%Property{
name: "Property C",
value: 200000
}
]
})
最后,我的问题是:如何将 John Doe
的 Property C
的值从 200000
更新为 300000
?如果 John Doe
买了一个 Property D
:
%Property{
name: "Property D"
value: 400000
}
如何将其添加到他的 properties
数据库中? (我正在使用 Postgres)。
最简单的方法是获取记录,更新 properties
列出并保存更改:
owner = Repo.get!(Owner, 1)
properties = owner.properties
# update all properties with name "Property C"'s value to 400000
properties = for %Property{name: name} = property <- properties do
if name == "Property C" do
%{property | value: 400000}
else
property
end
end
# add a property to the start
properties = [%Property{name: "Property D", value: 400000} | properties]
# or to the end
# properties = properties ++ [%Property{name: "Property D", value: 400000}]
# update
Owner.changeset(owner, %{properties: properties})
|> Repo.update!
你可以使用JSON函数做一些操作(至少插入一个属性)
由 PostgreSQL 使用提供
fragment
但我认为您无法搜索和有条件地更新项目
使用它们的数组。