Ecto,Phoenix:如何使用embeds_many声明更新模型?

时间:2017-02-07 15:03:23

标签: postgresql elixir phoenix-framework ecto

我有两个模型OwnerProperty,其中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)。

1 个答案:

答案 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但我不认为您可以搜索并有条件地更新项目 使用它们的数组。