如何使用Ecto更新嵌入式列表中的一个子文档?

时间:2016-07-12 13:17:26

标签: mongodb elixir phoenix-framework ecto

我有一个包含子文档嵌入列表的文档。如何使用Ecto更新/更改嵌入列表中的某个特定文档?

defmodule MyApp.Thing do
  use MyApp.Model

  schema "things" do
    embeds_many :users,  User
  end
end


defmodule MyApp.User do
  use MyApp.Model

  embedded_schema do
    field :name,  :string
    field :email, :string
    field :admin, :boolean, default: false
  end
end

defmodule MyApp.Model do
  defmacro __using__(_) do
    quote do
      use MyApp.Web, :model
      @primary_key {:id, :binary_id, autogenerate: true}
      @foreign_key_type :binary_id # For associations
    end
  end
end

1 个答案:

答案 0 :(得分:0)

到目前为止,我的解决方案是生成除了我要更新的用户之外的所有用户的列表,并创建一个用户的变更集和其他用户的新列表,然后在该事物上put_embed此列表。它有效,但感觉必须有一个更优雅的解决方案。

user        = Enum.find(thing.users, fn user -> user.id == user_id end)
other_users = Enum.filter(thing.users, fn user -> user.id != user_id end)
user_cs     = User.changeset(user, %{email: email})
users       = [user_cs | other_users]

thing
|> Ecto.Changeset.change
|> Ecto.Changeset.put_embed(:users, users)
|> Repo.update

编辑:我刚刚发现了这个“解决方案”的严重陷阱。未受影响的用户也会更新,这可能是同意呼叫(竞争条件)的问题。所以必须有另一种解决方案。