Postgresql: How to index jsonb array of objects column
The following code will be able to use a GIN index on the jsonb column:

SELECT COUNT(*) FROM results
WHERE subjects @&gt; '[{"subject": "B/MATH", "grade": "A"}]'


The difference to your example is that I don't unpack the array, I just query the jsonb column directly. The GIN index can be used for the @> operator on jsonb columns, but it can't be used for arbitrary functions. You're using the @> operator in the end, but not on the actual jsonb column but on your extracted json.

Indexing a LIKE condition with a wildcard at the beginning is far, far more difficult. You would need a trigram index for this, but I've no idea how to use one for data inside an array in a jsonb column, if that is even possible. You should strongly consider storing this information in a more formal way that avoids having to use LIKE at all.

A LIKE that doesn't have a wildcard at the beginning like 'MATH%' can use a btree index under some conditions (see https://www.postgresql.org/docs/9.5/static/indexes-types.html for some details, you have to pay attention to the locale for this). 

If this weren't an array, but a plain object inside the jsonb column, you could use a functional index like e.g.

CREATE INDEX ON results((subject-&gt;&gt;'grade'));


This is maybe also possible with an array inside jsonb, but I can't think of a reasonable way to do this right now.

Your current schema makes everything an order of magnitude more difficult to write and makes it very hard to impossible to properly take advantage of indexes. If you have the option, consider storing this data in a table with a subject and a grade column, this would make this problem far easier.