Ecto: why Repo.get before Repo.update

Hello,

In many samples and documentation, we can see the following pattern to update a resource (let say from a schema based Score module):

Repo.get!(Score, id)
|> Score.changeset(attrs)
|> Repo.update()

In some cases, there’s no need to know the pre-existing value of a record. Is there a problem in winning a DB-hit by using the struct directly:

%Score{id: id}
|> Score.changeset(attrs)
|> Repo.update()

Thanks!

1 Like

I think the latter will update all fields in the database (which are given in the changeset) even if they haven’t changed. This is usually more expensive than first reading the values and only writing back what has changed.

4 Likes

I think you’re right. Maybe in some cases (with narrow changesets), not fetching the resource can be interesting.

Take a look at Repo.update_all(). It takes a query and executes the UPDATE statement in the DB, no prior fetching required.

2 Likes

You could avoid fetch the database with update doing this:

%Score{id: id}
|> Ecto.Changeset.cast(attrs)
|> Repo.update()

Only the fields specified at attrs will be modified, since they will fill the changes field in the changeset.

8 Likes