denis

denis

Ecto fragment jsonb[] interpolation

Hi, I’m running into problems when trying to interpolate somewhat “simple” json query using a fragment.

I have a jsonb column in postgres that has the following structure (array of objects):

[{"name": "test", ...}, {"name": "another", ...}, ...]

Let’s start with the SQL query that gets me what I need:

SELECT count(*) 
FROM "posts" AS p0 
WHERE (p0."jsonb_column" @> ANY( ARRAY [ '[{"name": "test"}]', '[{"name": "another"}]' ]::jsonb[]));

Translated to ecto (without parametrised variables) this works just fine:

from(p in Post,
        where:
          fragment(
            "? @> ANY (ARRAY['[{\"name\":\"test\"}]','[{\"name\": \"another\"}]']::jsonb[])",
            p.jsonb_column
          )
      )
|> Repo.aggregate(:count)

However when I use parametrised values it ends up generating a slightly different sql query, which obviously doesn’t return the same results. This is the closest I can get it:

vals = [[%{"name" => "test"}], [%{"name" => "another"}]]

from(
        p in Post,
        where:
          fragment(
            "? @> ANY (ARRAY [?]::jsonb[])",
            p.jsonb_column,
            ^vals
          )
      )
|> Repo.aggregate(:count)

This generates the following SQL:

SELECT count(*) FROM "posts" AS p0 WHERE (p0."jsonb_column" @> ANY (ARRAY [$1]::jsonb[]))

with parameters: $1 = '[[{"name": "test"}], [{"name": "another"}]]'
correct parameters would be: '[{"name": "test"}]', '[{"name": "another"}]'

Any ideas about how can I get this to work? Cheers!

First Post!

al2o3cr

al2o3cr

I don’t think ARRAY is going to do what you want - ARRAY[$1] means an array with exactly one element taken from the bind parameters.

What might work better is passing the list serialized as a SQL array of JSON:

$1 = '{"{\"name\": \"test\"}", "{\"name\": \"another\"}"}'

Then the consuming code looks like ? @> ANY(?::jsonb[])

You may need to supply additional type information for vals to make this work.

Last Post!

denis

denis

Thanks @al2o3cr, I tried this approach too by serializing values individually within a list, however it still doesn’t produce the correct results. Not sure if I’m doing it correctly though…

vals = [[%{"name" => "test"}], [%{"name" => "another"}]]
serialized = vals |> Enum.map(fn x -> x |> Jason.encode!() end)

with fragment being:

fragment("? @> ANY(?::jsonb[])",
    p.services,
    ^serialized
)

I don’t think this is necessary, because the raw sql query works as expected without it, it’s just I can’t get ecto to do the same thing :face_with_head_bandage:

Where Next?

Popular in Announcing Top

alisinabh
Hey everyone i’ve developed a library for Jalaali calendar for elixir which supports converting Gregorian dates to Jalaali and vice vers...
New
mischov
import Meeseeks.CSS html = HTTPoison.get!("https://news.ycombinator.com/").body for story <- Meeseeks.all(html, css("tr.athing")) do...
New
michalmuskala
Hello everybody. I have just released Jason - a new JSON library. You might be wondering, why do we need a new library? The primary foc...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 44265 214
New
oltarasenko
Dear Elixir community, After a year of development, bug fixes, and improvements, we are proudly ready to share the release of Crawly 0.1...
New
kip
Image is an image processing library for Elixir. It is based upon the fabulous vix library that provides a libvips wrapper for Elixir. I...
622 19610 194
New
martinthenth
Hello everybody :wave: Recently, some of my colleagues talked about database ids and uuids and their problems, and I remembered the pain...
New

Other popular topics Top

Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
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
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New

We're in Beta

About us Mission Statement