使用Ecto(MySQL)进行upsert的最简单方法是什么?

Teo*_*ing 11 mysql elixir ecto phoenix-framework

在我的应用程序中执行upsert很常见,我想实现最简洁的方法来实现upsert.

  1. 我应该使用片段来实现本机sql upsert吗?
  2. 任何惯用的ecto方式做upsert?

Ale*_*ush 21

您可以使用Ecto.Repo.insert_or_update/2,请注意,为此,您必须从数据库加载现有模型.

 model = %Post{id: 'existing_id', ...}
 MyRepo.insert_or_update changeset
 # => {:error, "id already exists"}
Run Code Online (Sandbox Code Playgroud)

例:

result =
  case MyRepo.get(Post, id) do
    nil  -> %Post{id: id} # Post not found, we build one
    post -> post          # Post exists, let's use it
  end
  |> Post.changeset(changes)
  |> MyRepo.insert_or_update

case result do
  {:ok, model}        -> # Inserted or updated with success
  {:error, changeset} -> # Something went wrong
end
Run Code Online (Sandbox Code Playgroud)


Art*_*sun 7

在我的例子中,insert_or_update由于唯一索引约束而引发了错误

对我有用的是Postgres v9.5通过on_conflict参数更新插入:

(考虑到唯一的列称为user_id

changeset
|> MyRepo.insert(
    on_conflict: :replace_all,
    conflict_target: :user_id
)
Run Code Online (Sandbox Code Playgroud)