Ecto Query merge new key into a struct

Is there a possibility to use https://hexdocs.pm/ecto/Ecto.Query.API.html#merge/2 to first transform the struct on the left hand side to a map, so that new keys can be added?

from(city in City, select: merge(city, %{new_field: "some_value"}))

so the return value would be a map instead of a struct.

Something like this, if map/1 would exist that would just return the full map

from(city in City, select: merge(map(city), %{new_field: "some_value"}))

My use case is the following. I want to find all duplicates and mark them.

I’m taking inspiration from the query from: https://blog.theodo.com/2018/01/search-destroy-duplicate-rows-postgresql/

SELECT * FROM
  (SELECT *, count(*)
  OVER
    (PARTITION BY
      firstname,
      lastname
    ) AS count
  FROM people) tableWithCount
  WHERE tableWithCount.count > 1;

and want to do this with subquery and for that I need to return a map.

Why not to add virtual field to City schema and use struct instead of map?

1 Like

That could work but feels not very clean, too add a virtual field that I would only use in one query

Then this code should help you

from city in City,
    select: merge(map(city, ^City.__schema__(:fields)), %{new_field: "some_value"})

But keep in mind, that you’re not limited to flat maps.

from city in City, select: {city, "some_value"}
from city in City, select: [city, "some_value"]
from city in City, select: %{city: city, new_field: "some_value"}

^ in these examples you’ll have a city struct as a part of other term like tuple, list or map

2 Likes