我有两个模型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
的{{1}}的值从Property C
更新为200000
?如果300000
购买John Doe
:
Property D
如何将其添加到数据库中的%Property{
name: "Property D"
value: 400000
}
? (我正在使用Postgres)。
答案 0 :(得分:3)
最简单的方法是获取记录,更新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 functions
provided by PostgreSQL进行一些操作(至少插入属性)
fragment
但我不认为您可以搜索并有条件地更新项目
使用它们的数组。