drapermd

drapermd

Upsert map in jsonb map array

So here is the code I came up with to generically generate an array param that will be stored on a jsonb property in ecto.

It only handles the root level, and is pretty limited, but I’m curious if the community has a better/more elegant/easier solution than I do. Let me re-phrase, I really believe you do, I just wanted to solicit advice.

Problem: jsonb array of objects stored on an Ecto model, these objects can be updated or added.

  @doc "if the id is in the map already, update it, otherwise append it"
  defp upsert_embed(%{id: id} = params, collection) when is_list(collection) do
   case Enum.find(collection, &(&1.id == id)) do
     nil -> collection ++ [params]
     found -> updated = Map.merge(found, params)
              collection = collection -- [found] ## This is the piece I'm really not confident in.
              collection = collection ++ [updated]
   end
  end
  @doc "provided map doesn't have an id"
  defp upsert_embed(%{} = params, collection) when is_list(collection) do
    collection ++ [params]
  end

  @doc """
  adds or updates a child object of an array of maps.
  """
  def upsert_embedded_field(%__struct__{} = struct, key, %{} = candidate_params) do
    updated_embeds = Map.get(struct, key) || []
    updated_embeds = case length(updated_embeds) do
       0 ->
          upsert_embed(candidate_params, updated_embeds)
       _ ->
          updated_embeds = Enum.reduce(updated_embeds, updated_embeds,  fn(e, collection) ->
            upsert_embed(candidate_params, collection)
          end)
       end
     # Return the mutated list
      updated_embeds
  end

Most Liked

drapermd

drapermd

Unfortunately Mongodb has serious security problems, and has had data retention issues in the past and honestly very slow for map reduce, search and math. I’ve deployed 6-9 apps on MongoDB and I like it for some things, but in my day job we have been urged to move all apps off of Mongo as soon as possible so when it comes to my hobby projects I am veering away from it now completely.

Postgres is vastly more feature-rich, time tested, performant, and out-performs Mongo for most NoSQL operations. I will switch frameworks before I switch the datastore. Languages come and go, but data storage is too important to make concessions on, and with Postgres there is no compromise, it just does exactly what I need it to do.

Now if only Ecto were as feature-rich :smiley:

mudasobwa

mudasobwa

Creator of Cure

NoSQLMongoDB though.

CouchDB is pure erlang. Also, Riak, Cassandra, RethinkDB and many more.

sorentwo

sorentwo

Oban Core Team

There are Postgres operators to do this directly on the jsonb column in an atomic way. You will need to use a fragment and play with the arguments a little bit.

The list of operators is in the postgresql docs. You are looking for jsonb_set in particular.

The Postgres adapter in my Flippant library has an example of doing upsert with an array on a jsonb column:

It is a bit complicated but works perfectly and is entirely atomic.

drapermd

drapermd

Is there robust ecto support for couchdb?

Where Next?

Popular in Guides/Tuts Top

voltone
The EEF’s Security WG has released the first public draft of the Secure Coding and Deployment Hardening Guidelines for BEAM languages. “...
New
siever
I just wrote a simple guide on how you can setup a productive elixir development environment in vim. Its really easy, just a few steps. ...
New
tomciopp
TLS 1.3 has been out for a little over a year now, but it has been unavailable in Phoenix due to erlang’s handling of ssl. With the most ...
New
marcelo
I wrote a small article on how to use current_user with coherence on Phoenix. There are already a couple of blogposts about it but I thin...
New
eclark
I’ve been working on a phoenix project lately and I wanted to use the latest versions of everything. Webpack 5 had some breaking changes ...
New
OvermindDL1
Ran across this recently, it's a set of cheatsheet inforgraphic things of the OTP behaviours on the BEAM:
New
emilsoman
Hello, While answering a StackOverflow question on how to debug an elixir node running remotely, I thought it may be helpful to write a...
New
wfgilman
I'm writing up this quick "How to" because what I thought was going to be an easy implementation of a Plug to validate a webhook request ...
New
Eiji
Hey, today I give amnesia library a try and found a few problems. I would like describe how to setup it properly and solve problems which...
New
AstonJ
..or as and when you can think of one :icon_cool: This thread my also be of interest: What took you way too long to figure out? :003:
New

Other popular topics Top

Qqwy
Update: How to use the Blogs & Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3268 119930 1237
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 th...
New
dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New

We're in Beta

About us Mission Statement