iog-kc

iog-kc

Select_merge with dynamic fields on a left outer join

We have a query that does a left outer join on a child table and then uses select_merge to merge dynamically selected fields from the child row into the parent. However, when there is no child row, the call to map fails with cannot merge because the right side is not a map, got: nil. Is there a way to get the call to map to use an empty map for merging when there isn’t a row to merge?

As a simplified example (assume that Product exists and has virtual fields for the translated fields in
Product.Translation), we have the function below where the translated_fields are provided contextually (for a product list, you might just want the name, but on a product display page, you want the description as well):

def product_with_translations(sku_code, locale, translated_fields \\ ~w(name)a) do
  Product
  |> from(as: :product)
  |> where(sku_code: ^sku_code)
  |> join(
    :left, [product: p],
    t in Product.Translation,
    on: t.product_id == p.id and t.locale == ^locale,
    as: :translation
  )
  |> select([product: p], p)
  |> select_merge([translation: t], map(t, ^translated_fields))
end

As long as the associated Product.Translation exists, this works beautifully. However, if we were to ask for locale de-DE and don’t have it we receive an ArgumentError:

iex> Repo.one(product_with_translations("123", "fr-CA", ~w(name description)a))
** (ArgumentError) cannot merge because the right side is not a map, got: nil

Nominally, it seems that this should work, but how can we make map produce a default empty map on a left outer join? Or is this an Ecto bug or missing feature?

First Post!

fuelen

fuelen

Are translated_fields really dynamic?
If no, then I’d recommend to use simpler select expression:

|> select([product: p, translation: t], %{p | name: coalesce(t.name, p.name)})

actually, multiple select_merge can be composed:

translated_fields
|> Enum.reduce(query, fn
  # it would be great to have something like this:
  # field, query ->
  #   query |> select_merge([product: p, translation:t], %{^field => coalesce(field(t, ^field), field(p, ^field))})
  # but dynamic atoms are not supported as a field key
  :name, query ->
    query
    |> select_merge([product: p, translation: t], %{name: coalesce(t.name, p.name)})
  :description, query ->
    query
    |> select_merge([product: p, translation: t], %{description: coalesce(t.description, p.description)})
end)

Where Next?

Popular in Questions Top

lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
Kurisu
For example for a current url like http://localhost:4000/cosmetic/products?_utf8=✓&query=perfume&page=2, I would like to get: ...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
vac
Hi, I’m quite new in Elixir and I’m trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and I...
New
JulienCorb
I am trying to implement my new.html.eex file to create new posts on my website. new.html.eex: <h1>Create Post</h1> <%= ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Other popular topics Top

Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New

We're in Beta

About us Mission Statement