1

Given this function:

CREATE OR REPLACE FUNCTION extract_key(
  i_m JSONB,
  i_key TEXT
) RETURNS JSONB AS $$
BEGIN
  RETURN i_m -> i_key;
END;
$$ LANGUAGE 'plpgsql';

I'd like to write a function extract_key_array where:

SELECT extract_key_array('hello', '[{"hello": {"id": 1}} ,{"hello": {"id": 2}}]')

outputs a json array: '[{"id": 1},{"id": 2}]'

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
zcaudate
  • 13,998
  • 7
  • 64
  • 124

2 Answers2

2

Your answer is basically good. A couple of improvments:

CREATE OR REPLACE FUNCTION extract_key_array(_key text, _arr jsonb)
  RETURNS jsonb
  LANGUAGE sql STABLE PARALLEL SAFE AS
$func$
SELECT jsonb_agg(elem -> _key) FROM jsonb_array_elements(_arr) elem;
$func$;

Works with your desired function call:

SELECT extract_key_array('hello', '[{"hello": {"id": 1}} ,{"hello": {"id": 2}}]')

db<>fiddle here

  • A simple SQL function does the job and can be inlined.

  • Declare the function STABLE and PARALLEL SAFE (because it is!) This allows for various optimizations in query plans.
    (Don't declare it IMMUTABLE as the contained jsonb_agg() is only STABLE for some unknown reason.)

  • You answer switched the order of function parameters displayed in the question.

About function inlining:

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
0

This works but maybe there's a faster method.

CREATE OR REPLACE FUNCTION extract_key_array(
  i_arr JSONB,
  i_key TEXT
) RETURNS JSONB AS $$
BEGIN
  RETURN jsonb_agg(extract_key(out,i_key)) FROM jsonb_array_elements(i_arr) AS out;
END;
$$ LANGUAGE 'plpgsql';
zcaudate
  • 13,998
  • 7
  • 64
  • 124