Default value for map in Ecto migration

I have a migration of type “map”. How can I set a default value for it? The %{} throws an exception.

Can you please provide some example code which shows how you have set up your schema and the exact error message you got?

Migration. Type of a field is map. How to set its default value?

When using postgres, it uses the jsonb datatype internally. So this works to set a default value:

  def change do
    create table :sometable do
      add :map_column, :map, default: "{}"
    end
  end

I don’t know if this works with mysql or other storage backends, as it relies on {} being able to be cast to a map in the store. But it works just fine with postgresql, at least :slight_smile:

2 Likes

Ok. For ecto there’s no difference between “map” and “jsonb” data types in a migration, right?

On postgres, yes. If using MySQL it just uses a text field. One more reason to use postgres :slight_smile:

2 Likes

Just discovered something interesting … you can alter the datatype used for storing maps in postgres with the postgres_map_type env varaible. There is this in the ecto mix.exs:

  def application do
    [applications: [:logger, :decimal, :poolboy],
     env: [json_library: Poison, postgres_map_type: "jsonb"], mod: {Ecto.Application, []}]
  end

neat. and since you can muck with the json_library, i wonder if it would be possible to be truly evil and store :map types as something completely different using a “json” library that doesn’t actually encode/decode between Elixir Maps and json … sounds horrible and evil, but it does make me curious :slight_smile:

2 Likes

Small update, just created a pull request to make this work as you expected (which I agree is reasonable given the principle of least astonishment): https://github.com/elixir-ecto/ecto/pull/2090

2 Likes

On postgres, yes. If using MySQL it just uses a text field.

FWIW, MySQL 5.7 has a native JSON datatype.

AFAIK MariaDB still doesn’t, though, and that’s the standard in most (all?) Linux distros … MariaDB has that imho rather odd JSON_VALUE function. So the divergence begins.

Perhaps the specific version of MySQL / MariaDB could be detected via the version() function, or it could be a feature option controled via configuration … and then the MySQL Ecto driver could start using that?

I dunno, MySQL/MariaDB-land just never seems to get out of the weeds …

I meant in Phoenix application, for Ecto.

But it already was jsonb for postgres by default.

Yes, however I was noting that this can actually be changed via configuration … which is more flexible than I expcted tbh.

Cheers …

The pull request was merged this morning by @josevalim so this should work as you expected it would in an upcoming release of Ecto … Huzzah! :smile:

3 Likes