Why doesn't ecto support dynamic map query

In sql you can use as keyword to give columns alias names . Why can’t we do this in ecto.

Like dynamically put map in a query.

Currently it supports dynamic queries like this(in list):

    iex(18)> fields = [:id]                                                                  
       [:id]

  iex(19)> fields_map = %{id: :job_id}                                                     
    %{id: :job_id}

  iex(20)> query = from p in Qber.V1.JobModel, where: p.id == 1, select: map(p, ^fields)
  #Ecto.Query<from j in Qber.V1.JobModel, where: j.id == 1, select: map(j, [:id])>

instead of using fieldsI want to use the fields_map

I want dynamic solution.

Is there any workaround?
Like using fragments to inject sql

Use select with a map syntax.

from(c in City, select: %{n: c.name, answer: 42})
1 Like

Thanks for your reply. I knew about map syntax. I want dynamic solution. I updated the question as well.

If I understand you correctly, maybe you can “remap” the keys after you receive the results?

But I think thats not the ideal solution to remap them later. It will complicate things.

Are you trying to always map the column to to some other value? or just for this query?

Always map it with some other value thats why need dynamic solution

One can take the opposite point of view - that in fact you are conflating activities and therefore making things more complicated by doing too many things at once.

With Ecto focus on getting the right data. Once you already have the data, transform it into the right shape. And re-keying a map is only one helper function away.

defmodule Demo do

  def rekey(source, mappings) do
    mapper =
      fn ({from, to}, target) ->
        case Map.fetch(source, from) do
          {:ok, value} ->
            Map.put(target, to, value)
          _ ->
            target
        end
      end

    List.foldl(mappings, %{}, mapper)
  end

end

s = %{id: 1, name: "JOB", junk: 999}
from_to = [id: :job_id, name: :job_name, not_junk: :job_not_junk]
t = Demo.rekey(s,from_to)

IO.inspect(t)
$ elixir demo.exs
%{job_id: 1, job_name: "JOB"}
$
5 Likes