Search code examples
elixirecto

case statement is setting as model in select merge


These are the params:

 %{
  "$select" => %{
    "$avg" => ["arrive_at"],
    "$count" => ["arrive_at"],
    "$fields" => ["id"],
    "$max" => ["cost"],
    "$min" => ["arrive_at"],
    "$sum" => ["arrive_at"]
  }
 }

This is the code:

 select when is_map(select) ->
        query = from(p in queryable, select: %{})

        fields =
          Enum.reduce(select, [], fn {key, value}, fields ->
            Enum.reduce(value, query, fn {k, v}, query ->
              case k do
                "$avg" ->
                  val = Enum.at(v, 0)

                  query =
                    from(
                      p in query,
                      select_merge: %{avg: avg(field(p, ^String.to_atom(val)))}
                    )

                "$count" ->
                  val = Enum.at(v, 0)

                  query =
                    from(
                      p in query,
                      select_merge: %{count: count(field(p, ^String.to_atom(val)))}
                    )

                "$min" ->
                  val = Enum.at(v, 0)

                  query =
                    from(
                      p in query,
                      select_merge: %{min: min(field(p, ^String.to_atom(val)))}
                    )

                "$max" ->
                  val = Enum.at(v, 0)

                  query =
                    from(
                      p in query,
                      select_merge: %{max: max(field(p, ^String.to_atom(val)))}
                    )

                "$sum" ->
                  val = Enum.at(v, 0)

                  query =
                    from(
                      p in query,
                      select_merge: %{sum: sum(field(p, ^String.to_atom(val)))}
                    )

                "$fields" ->
                  fields = Enum.at(v, 0)
                  IO.inspect(fields)
              end
            end)
           end)
         end

If I run this code without the $fields statement . It returns the select merge query correctly.

But if I ran it with $fields. It gives me the error.

  (Protocol.UndefinedError) protocol Ecto.Queryable not implemented for [:id]

Its taking the value of the $fields as my model name and using it in query

Why its behaving like that?. Taking the value of the $fields as my model.

Any help will be much appreciated.

Thanks.


Solution

  • You have to return anything, that has an Ecto.Queryable implementation (namely Ecto.Query,) and your code is currently returning a List (fields.) Don’t forget you are inside reduce and the returned value is an accumulator. FWIW,

    "$fields" ->
      fields = Enum.at(v, 0)
      IO.inspect(fields)
      query   # ⇐ NOTE THE RETURNED VALUE 
    

    will work as a stub until the proper implementation.