Help with Ecto select_merge/3

I have a generic query for Transfers in my system. I’d like to restrict the results by doing an inner join on another table, and then adding an attribute to the results. I’m using select_merge/3 for this but getting a KeyErrror and can’t figure out why. Any ideas?

This query gets all transfer for a user:

  def resource(user) do
    from t in Transfer,
      join: ta in assoc(t, :to_account),
      join: u in assoc(ta, :user),
      join: s in assoc(t, :savings),
      preload: [savings: s],
      where: u.id == ^user.id
  end

Joins to a table to get the subset of transfer. I’d like to then add the field %{type: "boost"} to the results of my query so I know that these are “boost” transfers.

  def all_boosted(user) do
    resource(user)
    |> join(:inner, [_t, _ta, _u, s], b in assoc(s, :boost))
    |> select_merge([t], %{type: "boost"})
    |> Repo.all()
  end

I get the following error:

** (KeyError) key :type not found
    (ecto) lib/ecto/repo/queryable.ex:207: anonymous fn/2 in Ecto.Repo.Queryable.process/5
    (stdlib) lists.erl:1263: :lists.foldl/3
    (ecto) lib/ecto/repo/queryable.ex:207: Ecto.Repo.Queryable.process/5
    (ecto) lib/ecto/repo/queryable.ex:180: anonymous fn/4 in Ecto.Repo.Queryable.postprocessor/4
    (elixir) lib/enum.ex:1255: Enum."-map/2-lists^map/1-0-"/2
    (ecto) lib/ecto/repo/queryable.ex:139: Ecto.Repo.Queryable.execute/5
    (ecto) lib/ecto/repo/queryable.ex:37: Ecto.Repo.Queryable.all/4
1 Like

Does your schema (for Transfer?) have type field?

2 Likes

Nope. I was under the impression you could use select_merge/3 to add an field to the query results :grimacing:

1 Like

If it is a map, not a struct. :slight_smile:

1 Like

Hmmm

The left-side of a merge can be a struct or a map. The right side must always be a map. If the left-side is a struct, the fields on the right side must be part of the struct, otherwise an error is raised.

https://hexdocs.pm/ecto/Ecto.Query.html#select_merge/3

Specifically this part. :wink:

3 Likes

Doh!

Totally missed that :joy:

2 Likes

Heh, there are a lot of docs. ^.^

If it is common, you can make a schema with that field as a ‘virtual’ field. Virtual fields do not exist in the database but are nice for you to stuff information into like via a query special syntax like that. :slight_smile:

I usually just use a map since structs are not statically typed anyway, so no real big boon there. ^.^;

Ohhh the virtual field is a good idea!

1 Like