Ecto postgrex hstore map any type

Hello there, I’m using an hstore column in postgres and it works well when in the model I define a map of strings
field :data, {:map, :string}

but how to accept other types? booleans, ints, etc?

(if is not possible) how to make all values to be strings before save?

For instance

"data": {
            "a": "aaa",
            "b": 29,
            "c": true
        }

errors: [data: {"is invalid", [type: {:map, :string}, validation: :cast]}]

@matt1 How about simply: field :data, :map?

https://hexdocs.pm/ecto/Ecto.Schema.html#module-primitive-types

If that does not helps you can always create your own custom type.

i have the error

** (FunctionClauseError) no function clause matching in Postgrex.Extensions.HStore.encode_hstore_value/1
    (postgrex) lib/postgrex/extensions/hstore.ex:42: Postgrex.Extensions.HStore.encode_hstore_value(4)
    (postgrex) lib/postgrex/extensions/hstore.ex:29: anonymous fn/2 in Postgrex.Extensions.HStore.encode_hstore/1
    (stdlib) maps.erl:257: :maps.fold_1/3
    (postgrex) lib/postgrex/extensions/hstore.ex:28: Postgrex.Extensions.HStore.encode_hstore/1
    (postgrex) lib/postgrex/type_module.ex:713: Postgrex.DefaultTypes.encode_params/3
    (postgrex) lib/postgrex/query.ex:62: DBConnection.Query.Postgrex.Query.encode/3
    (db_connection) lib/db_connection.ex:1148: DBConnection.encode/5
    (db_connection) lib/db_connection.ex:1246: DBConnection.run_prepare_execute/5
    (db_connection) lib/db_connection.ex:1342: DBConnection.run/6
    (db_connection) lib/db_connection.ex:540: DBConnection.parsed_prepare_execute/5
    (db_connection) lib/db_connection.ex:533: DBConnection.prepare_execute/4
    (postgrex) lib/postgrex.ex:161: Postgrex.query/4
    (ecto_sql) lib/ecto/adapters/sql.ex:661: Ecto.Adapters.SQL.struct/10
    (ecto) lib/ecto/repo/schema.ex:652: Ecto.Repo.Schema.apply/4
    (ecto) lib/ecto/repo/schema.ex:264: anonymous fn/15 in Ecto.Repo.Schema.do_insert/3

maybe I need to update Ecto. im using 3.0.8

Any particular reason why you want to use hstore (which is meant to contain homogenous types) rather than jsonb?

2 Likes

no, was recommendations in the forum to avoid jsonb

What? Where, by whom? IMHO you should go with jsonb by default unless there is explicit reason to not do so (ex. translations) as hstore can store only {string, string} pairs.

4 Likes

I don’t find where probably i’m wrong and wasn’t here.

I asked before something related Using Ecto postgrex hstore
but I guess I can change it if it’s the problem

well changing to jsonb it works so I will switch to that.

if helps somebody

 def up do
    execute "ALTER TABLE info ALTER COLUMN data TYPE JSONB USING CAST(data as JSONB);"
  end

and in the model

field :data, :map
4 Likes