johnnyicon

johnnyicon

How do I use the Postgres JSONB / Postgrex JSON extension?

Hi all,

I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage.

I’m trying to use Postgres’ JSONB via the :map datatype.

Here’s my migration to add it to my table:

defmodule MyApp.Repo.Migrations.AddMapFieldToUser do
  use Ecto.Migration

  def change do
    alter table(:users) do
      add :data, :map
    end
  end
end

Here’s my schema:

defmodule MyApp.User do
  use MyApp.Web, :model
  use Coherence.Schema

  schema "users" do
    field :first_name, :string
    field :last_name, :string
    field :email, :string
    field :data, :map

    coherence_schema()

    timestamps()
  end

  @doc """
  Builds a changeset based on the `struct` and `params`.
  """
  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, [:first_name, :last_name, :email] ++ coherence_fields)
    |> unique_constraint(:email)
    |> validate_required([:first_name, :last_name, :email])
    |> validate_coherence(params)
  end
end

I’ve been trying to set values into the data map using a changeset, but I haven’t had any luck. I’ve tried using both a JSON string and a map.

JSON string:

changeset = User.changeset(retrieved_user, %{data: "{test:'awesome'}"})
#Ecto.Changeset<action: nil, changes: %{}, errors: [],
 data: #MyApp.User<>, valid?: true>

Map:

changeset = User.changeset(john, %{data: %{test: "awesome"}})
#Ecto.Changeset<action: nil, changes: %{}, errors: [],
 data: #PodioBackup.User<>, valid?: true>

You’ll see that the changes map is empty.

Which leads me to believe that I am clearly missing something! :sweat_smile: And I’m thinking maybe I need to add this JSON extension that many websites are referring to: postgrex/lib/postgrex/extensions/json.ex at master · elixir-ecto/postgrex · GitHub

How do I actually use that JSON extension? And, what am I doing wrong?

Thanks for the help in advance! :slight_smile:

Marked As Solved

alexgaribay

alexgaribay

Phoenix Core Team

You’re missing a cast of :data in your changeset.

  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, [:first_name, :last_name, :data] ++ coherence_fields)
    |> ...
  end

Also Liked

michalmuskala

michalmuskala

They are equivalent when using postgres. map is an abstract type and each database adapter can choose the actual representation - for postgres it’s jsonb.

Qqwy

Qqwy

TypeCheck Core Team

So is a correct conclusion that using :map would be preferable over using :json, to allow you to switch database adapters, if desired, later on?

Where Next?

Popular in Questions Top

marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call t...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

Other popular topics Top

Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 42920 311
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
Lily
In templates/appointment/index.html.eex: &lt;%= for appointment &lt;- @appointments do %&gt; &lt;tr&gt; &lt;td&gt;&lt;%= appoi...
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31142 143
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New

Latest on Elixir Forum

We're in Beta

About us Mission Statement