Insert_all on_conflict replace one field possible?

From the docs there is something similar to this:

MyRepo.insert_all(Post, [%{title: "My first post", views: 10, inserted_at: NaiveDateTime.utc_now, updated_at: NaiveDateTime.utc_now}, %{title: "My second post", views: 20, inserted_at: NaiveDateTime.utc_now, updated_at: NaiveDateTime.utc_now}], on_conflict: [set: [views: ???]], conflict_target: :title)

This query is intended to insert posts and on the conflict of a unique title - simply update the Post.views field.

However the ??? part I don’t know how to resolve. How do I get access to the field views? All of the examples in the Ecto docs show set only replacing with a hardcoded value.

conflict_query = """ DO UPDATE SET title = EXCLUDED.title """

Tried to use this as an update query but I just get a query error.

2 Likes

I have exactly the same problem. Has anybody got an idea of how to do this one ?

2 Likes

Looks like this has been solved https://github.com/elixir-ecto/ecto/issues/2370

1 Like

So turns out that this is not released yet in Ecto but it is on master.

In the meantime…

query = from p in Post, update: [set: [title: fragment("EXCLUDED.title")]
Repo.insert_all Post, entries, on_conflict: query

Thanks to @josevalim (for the answer) and Dennis Beatty’s Lonestar Elixirconf 2018 talk for pointing it out.

2 Likes