1

I have a json field (stored as text) in a table and I want to extract certain items from the json that have a specified ID in a nested array (within the json).

Each json item has a type attribute and a value attribute. The value furthermore has a GRI attribute (array) which I would like to use to filter. Here is a sample of one streamfield column item:

[{"type": "paragraph", 
    "value": {"paragraph": "<p>Sample paragraph 91</p>", "GRI": [27, 91, 211]},
 {"type": "paragraph", 
    "value": {"paragraph": "<p>Sample paragraph 191</p>", "GRI": [13, 191, 271]}]

This query sort of works:

SELECT value FROM "sampletable" r, json_array_elements(r.streamfield::json) obj 
WHERE  obj->>'type' = 'paragraph' AND obj#>>'{value,GRI}' LIKE '%91%';

This would give me all items with ID 91. But also with ID 191, 291 etc...

So how can I convert the `obj#>>'{value,GRI}' statement into an array so that I can filter based on the specified ID?

Here is an SQLFiddle for this: http://sqlfiddle.com/#!15/184e1/1

Edit: clarified structure of JSON

2
  • Which version of PostgreSQL? Commented Jun 1, 2016 at 2:35
  • Postgres version 9.3.10 on AWS RDS Commented Jun 1, 2016 at 12:45

1 Answer 1

0

Here's how I would approach this. Basically, you need to return the items of the JSON array as a set, then create a PostgreSQL array from it.

DROP TABLE IF EXISTS "sampletable";
CREATE TEMP TABLE "sampletable" (streamfield TEXT);
INSERT INTO "sampletable" VALUES ('{"type": "paragraph", "value": {"paragraph": "<p>Sample paragraph 91</p>", "GRI": [27, 91, 211]}}');

-- Easier to separate out in a CTE, but this could be a subquery, if need be.
WITH cte AS
(
  SELECT
    (streamfield::JSON)->>'type' AS type_text,
    JSON_EXTRACT_PATH_TEXT(streamfield::JSON,'value','paragraph') AS paragraph_text,
    (SELECT ARRAY_AGG(col::INT) FROM JSON_ARRAY_ELEMENTS_TEXT(JSON_EXTRACT_PATH(streamfield::JSON,'value','GRI')) tbl(col)) AS gri_array -- This is an INT array now
  FROM
    "sampletable"
)

SELECT
  type_text,
  paragraph_text,
  gri_array
FROM
  cte
WHERE
  type_text = 'paragraph' AND
  91 = ANY(gri_array)
2
  • This seems like a good approach, but did you try it on the fiddle? I get an error: ERROR: function json_array_elements_text(json) does not exist Hint: No function matches the given name and argument types. You might need to add explicit type casts. Position: 193 Commented Jun 1, 2016 at 9:11
  • OK I've edited my question to clarify the data structure in the JSON field. Each streamfield column has a json array of elements. Could you please help me find a solution that addresses this structure? Commented Jun 1, 2016 at 10:06

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.