1

I have a jsonb column in the following format:

{
  "targets": {
    "01d7de90-57fd-4c4f-b7c9-3b956762fe25": {
      "id": "01d7de90-57fd-4c4f-b7c9-3b956762fe25",
      "name": "target1"
    },
    "0f43e1fe-132e-464b-8284-4a9947a70c1c": {
      "id": "0f43e1fe-132e-464b-8284-4a9947a70c1c",
      "name": "target2"
    }
  },
  "suggestions": [
    {
      "items": [
        {
          "id": "foo",
          "code": "item1"
        }
      ],
      "groupId": 1
    },
    {
      "items": [
        {
          "id": "bar",
          "code": "item2"
        }
      ],
      "groupId": 2
    }
  ]
}

I would like to return that same column but only with a subset of the "items" within "suggestions" subject to given item "id".

For example, if I am interested in item with id "foo", the return value should be:

{
  "targets": {
    "01d7de90-57fd-4c4f-b7c9-3b956762fe25": {
      "id": "01d7de90-57fd-4c4f-b7c9-3b956762fe25",
      "name": "target1"
    },
    "0f43e1fe-132e-464b-8284-4a9947a70c1c": {
      "id": "0f43e1fe-132e-464b-8284-4a9947a70c1c",
      "name": "target2"
    }
  },
  "suggestions": [
    {
      "items": [
        {
          "id": "foo",
          "code": "item1"
        }
      ],
      "groupId": 1
    }
  ]
}

I've tried several things so far, including:

SELECT *
FROM my_table
WHERE jsonb_array_length(my_column->'suggestions') > 0
  AND EXISTS (
    SELECT 1
    FROM jsonb_array_elements(my_column->'suggestions') AS suggestions(items)
    WHERE items->'items' @> '[{"id": "foo"}]'
  );

and also

SELECT *
FROM my_table
WHERE EXISTS (
  SELECT 1
  FROM jsonb_array_elements(my_column->'suggestions') AS suggestions(suggestion)
  WHERE EXISTS (
    SELECT 1
    FROM jsonb_array_elements(suggestion->'items') AS items
    WHERE items->>'id' = 'foo'
  )
);

Unfortunately, none of these worked. I've also tried to figure out how can I solve this with jsonb_path_query_array but the column is way too nested for me to figure out the appropriate query path.

Any help is appreciated!

2 Answers 2

0

To accomplish this, first recreate the items array using jsonb_agg, then replace the jsonb column using jsonb_set:

select my_column, jsonb_set(my_column::jsonb, '{suggestions}', items_updated::jsonb) edited
from (
  select my_column, jsonb_agg(items) as items_updated
  from my_table,
     jsonb_array_elements(my_column->'suggestions') as items
  where value->'items' @> '[{"id": "foo"}]'
  group by my_column
) as s

Demo here

Sign up to request clarification or add additional context in comments.

Comments

0

You just have to query your JSON in the path for suggestions and replace the result into the JSON tree like:

select my_column, 
jsonb_set(my_column, '{suggestions}', sel_item) my_result
from (  select my_column,  
        jsonb_path_query_array(my_column, 
        '$.suggestions[*] ? (@.items.id == "foo")') sel_item
        from my_table 
) as t;

Working sample here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.