Skip to content

Instantly share code, notes, and snippets.

@weiland
Created September 29, 2016 12:58
Show Gist options
  • Save weiland/042a895b319a38ec2cb5a66430f401d5 to your computer and use it in GitHub Desktop.
Save weiland/042a895b319a38ec2cb5a66430f401d5 to your computer and use it in GitHub Desktop.
Find or Create in Ecto
# two different ways to implement a find_or_create for Ecto
find_or_create_user = fn user ->
case Repo.all(from u in users, where: u.id == ^user.id and u.email == ^user.email) do
[] ->
%User{}
|> User.changeset(user)
|> Repo.insert!()
_ ->
IO.puts "Already inserted"
end
end
def find_or_create(user) do
query = from u in users,
where: u.uid == ^user.uid
if !Repo.one(query) do
Repo.insert(user)
end
Repo.one(query)
end
@wyozi
Copy link

wyozi commented Oct 4, 2020

@protestContent this is better but still not the exactly correct behavior. At least on Postgres the serial autoincrement id increases even with on_conflict: :nothing, so with enough find_or_create calls this will needlessly increase autoincrement IDs by quite a bit.

@protestContest
Copy link

@wyozi good point, I didn't realize that. Still better than a race condition imo. I wonder what the postgres community recommends in cases like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment