How to update field if changed using Ecto

ecto
postgres
Tags: #<Tag:0x00007fcf980866e0> #<Tag:0x00007fcf980865a0>

#1

Hi folks,
I’m working with football data in Mix project. My API does not support event system :frowning:. Way that I take data is time based (cron like). So far every record in Postgres tables have hash field based on data hash. If my hash is different than I go to update, else do nothing.
What is best way to do this logic? I’m thinking in model to create function that contains this logic (upsert_by_…), get record (by uniq id non AI) if exists, perform calculations and execute insert/update/nothing.
I’m working with hash to eliminate multi value comparison.


#2

It’s not a popular theme, let me show you some example:

defmodule Api.Upsert do

  alias Api.Repo

  defmacro __using__(_) do
    quote do
      def upsert(data) do
        record = Repo.get_by(__MODULE__, api_id: data.api_id)
        save_to_db(record, data)
      end

      defp save_to_db(nil, data) do
        IO.inspect data
        changeset = __MODULE__.changeset(data)
        IO.inspect changeset
        case Repo.insert(changeset) do
          {:ok, struct}        -> struct
          {:error, changeset} -> {:error, "Insert #{__MODULE__} failure!", changeset}
        end
      end

      defp save_to_db(record, data) do
        case String.equivalent?(record.hash, data.hash) do
          true -> record
          _    -> update(record, data)
        end
      end

      defp update(record, data) do
        changeset = __MODULE__.changeset(data, record)
        case Repo.update(changeset) do
          {:ok, struct}        -> struct
          {:error, changeset} -> {:error, "Update #{__MODULE__} failure!", changeset}
        end
      end

    end
  end
end

This macro is included in my models. Are you see some mistakes?


#3

I seriously cannot understand what exactly are you trying to achieve.

Instead of giving us details about your code, can you tell us what is your input and desired output?


#4

Hi, my goal is to store API data in DB. Data is big, so I decided to update them only if there is difference (cause update is very slow operation). My input data is models like Country{Name}, League{Name,Country}, Team{Name,Venue,League}, Fixtures{TeamA,TeamB,Date} and so on. And I do not want to write comparrisions manualy (it`s a ton of code).