drapermd

drapermd

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

Showing Posts 1 to 6

entone

entone

A NoSQL DB is much better suited for something like this. MongoDB has support for atomic operations on embedded fields, and all sorts of atomic array operations as well.

drapermd

drapermd OP

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

NoSQL ≠ MongoDB 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:

https://github.com/sorentwo/flippant/blob/master/lib/flippant/adapters/postgres.ex#L79

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

drapermd

drapermd OP

that is amazing thank you so much!

drapermd

drapermd OP

Is there robust ecto support for couchdb?

— All posts loaded —

Where Next? Top

Trending in Guides/Tuts Top

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews