Вы можете индексировать только числовые значения c, а не ключи, используя функциональные индексы. Вам, вероятно, нужно сделать вспомогательную функцию, чтобы сделать это.
create function jsonb_objarray_to_intarray(jsonb,text) returns int[] immutable language sql as
$$ select array_agg((x->>$2)::int) from jsonb_array_elements($1) f(x) $$;
create index on mytable using gin (jsonb_objarray_to_intarray(data->'list','nestedId'));
SELECT data FROM mytable where jsonb_objarray_to_intarray(data->'list','nestedId') @> ARRAY[3];
Я написал это таким образом, чтобы функцию можно было повторно использовать в других подобных ситуациях. Если вас не волнует повторное использование, вы можете сделать код, который его использует, красивее, жестко закодировав разыменование и значение ключа в функции:
create function mytable_to_intarray(jsonb) returns int[] immutable language sql as
$$ select array_agg((x->>'nestedId')::int) from jsonb_array_elements($1->'list') f(x) $$;
create index on mytable using gin (mytable_to_intarray(data));
SELECT data FROM mytable where mytable_to_intarray(data) @> ARRAY[3];
Теперь эти индексы принимают дольше, чем ваш оригинал, но они примерно вдвое меньше по размеру и по крайней мере так же быстро делают запросы. Что еще более важно, у планировщика есть лучшая статистика по избирательности, и поэтому при более сложных запросах, вероятно, придут лучшие планы запросов.