Ecto postgrex hstore map any type

ecto
phoenix
#1

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]}]

0 Likes

#2

@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.

0 Likes

#3

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
0 Likes

#4

maybe I need to update Ecto. im using 3.0.8

0 Likes

#5

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

1 Like

#6

no, was recommendations in the forum to avoid jsonb

0 Likes

#7

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.

3 Likes

#8

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

0 Likes

#9

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
3 Likes