# Ecto embedded schema migration

**URL:** <https://forum.elixirforum.com/t/ecto-embedded-schema-migration/13657>\
**Category:** Questions\
**Tags:** ecto, migrations\
**Created:** [April 13, 2018, 2:39pm UTC](https://forum.elixirforum.com/t/ecto-embedded-schema-migration/13657 "2018-04-13T14:39:51Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![euphbriggs](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/euphbriggs/32/18120_2.png) [@euphbriggs](https://forum.elixirforum.com/u/euphbriggs)\
**Post date:** [April 13, 2018, 2:39pm UTC](https://forum.elixirforum.com/t/ecto-embedded-schema-migration/13657/1 "2018-04-13T14:39:51Z")

</div>

I have a schema that contains an embedded schema, which I would like to rename a field on. For example:

```Elixir
schema "menu_items" do
    field(:plu, :string)
    # ...
    embeds_many :build_items, BuildItem, on_replace: :delete do
        field(:item_id, :string)
        # ...
    end
end

```

I want to rename the `build_items` `item_id` field to `value`. Is there a way to do this with an Ecto migration or will I need to create the new field, copy the data over, then delete the old field?

Any pointers are very much appreciated.

Thanks,  
Ben

---

<div class="post-metadata">

**Author:** ![idi527](https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/i/85e7bf/32.png) [@idi527](https://forum.elixirforum.com/u/idi527)\
**Post date:** [April 13, 2018, 3:29pm UTC](https://forum.elixirforum.com/t/ecto-embedded-schema-migration/13657/2 "2018-04-13T15:29:03Z")

</div>

You could probably add an sql statement to [`execute`](https://hexdocs.pm/ecto/Ecto.Migration.html#execute/1) which would atomically move your json fields around during an `up` migration. Don’t forget to include a `down` migration which would try and reverse that.

Adapted from [https://stackoverflow.com/questions/42308764/postgresql-rename-attribute-in-jsonb-field](https://stackoverflow.com/questions/42308764/postgresql-rename-attribute-in-jsonb-field)

```elixir
def SomeMigration do
  use Ecto.Migration

  def up do
    execute("""
    update menu_items
      set build_item = build_item - 'item_id' || jsonb_build_object('value', js->'item_id');
    """)
  end
  
  def down do
      # ... do the opposite
  end
end

```

---

<div class="post-metadata">

**Author:** ![euphbriggs](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/euphbriggs/32/18120_2.png) [@euphbriggs](https://forum.elixirforum.com/u/euphbriggs)\
**Post date:** [April 13, 2018, 3:37pm UTC](https://forum.elixirforum.com/t/ecto-embedded-schema-migration/13657/3 "2018-04-13T15:37:40Z")

</div>

I didn’t think about writing the SQL manually, that’s a great idea! Maybe you should relinquish your handle and give it to me. 🙂

Thanks!

---

<div class="post-metadata">

**Author:** ![idi527](https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/i/85e7bf/32.png) [@idi527](https://forum.elixirforum.com/u/idi527)\
**Post date:** [April 13, 2018, 3:48pm UTC](https://forum.elixirforum.com/t/ecto-embedded-schema-migration/13657/4 "2018-04-13T15:48:33Z")

</div>

Actually, the stackowerflow answer from above won’t work since you seem to have an array of jsons, not just one json object … So I think I’ll keep my handle for now.

But yeah, I would still do it “manually” with an SQL statement, albeit with a different one.

---

<div class="post-metadata">

**Author:** ![euphbriggs](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/euphbriggs/32/18120_2.png) [@euphbriggs](https://forum.elixirforum.com/u/euphbriggs)\
**Post date:** [April 21, 2018, 12:13pm UTC](https://forum.elixirforum.com/t/ecto-embedded-schema-migration/13657/5 "2018-04-21T12:13:46Z")

</div>

I posted [this question](https://stackoverflow.com/questions/49904978/postgresql-jsonb-migration-rename-attribute) on StackOverflow and here’s the solution that I ended up with. Thanks for pointing me in the right direction. I think I probably would have wasted another day’s worth of time before I even considered writing the SQL directly. Ecto’s really spoiled me. I used to write all my SQL queries/commands and now I rarely need to!

```
UPDATE menu_items
SET build_items = t.newValue
FROM (WITH temp AS (SELECT id, UNNEST(build_items) b FROM menu_items)
    SELECT
      id,
      array_agg(b - 'item_id' || jsonb_build_object('value', coalesce(b -> 'item_id', b -> 'value'))) AS newValue
    FROM temp
    GROUP BY id) AS t
WHERE menu_items.id = t.id;

```

---

<div class="post-metadata">

**Author:** ![zaljir](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/zaljir/32/26789_2.png) [@zaljir](https://forum.elixirforum.com/u/zaljir)\
**Post date:** [May 21, 2026, 9:42am UTC](https://forum.elixirforum.com/t/ecto-embedded-schema-migration/13657/6 "2026-05-21T09:42:24Z")

</div>

Old topic, but still useful. The custom query can be simplified a little:

```elixir
    UPDATE menu_items t1 SET build_items = (
      SELECT json_agg(el::jsonb - 'item_id' || jsonb_build_object('value', el -> 'item_id')) 
      FROM menu_items t2, jsonb_array_elements(t2.build_items) AS el
      WHERE t1.id = t2.id
    );  

```
