PostgreSQL operator uses index but underlying function does not
Supported operators and workaround

The default operator class for GIN indexes on json columns jsonb_ops only supports these operators (per documentaion):


Name        Indexed Data Type   Indexable Operators
...
jsonb_ops   jsonb               ? ?&amp; ?| @&gt;



You can achieve this the other way round: Create a simple IMMUTABLE SQL function using the ? operator, which can be inlined and will use the index just like the operator itself:

CREATE OR REPLACE FUNCTION jb_contains(jsonb, text)
  RETURNS bool AS
'SELECT $1 ? $2' LANGUAGE sql IMMUTABLE;


This works, I tested in Postgres 9.4 ...

Misunderstandings

However, you have been asking the wrong question. There are two basic misconceptions in your question.


The jsonb operator ? cannot be used to search for values. Only for keys or array elements. The manual:


  Description:
  Does the string exist as a top-level key within the JSON value?


You got the wrong operator, the WHERE condition cannot work: WHERE d-&gt;'name' ? 'First'
The expression index you have doesn't makes sense either way

CREATE INDEX idx_jsonthings_name ON jsonthings USING GIN ((d->'name'));


The expression d-&gt;'name' returns a jsonb value. You would need d-&gt;&gt;'name' to get the value as text.
But that would still be pointless. Since the value of the name key is a simple string, a GIN index (while possible) makes no sense to begin with.



Solutions

You don't need the operator ? - so no workaround either.
Here are two ways that would actually work:


Plain GIN index on d and use the "contains" operator @&gt;:

CREATE INDEX idx_jsonthings_d_gin ON jsonthings USING GIN (d);

SELECT d FROM jsonthings WHERE d @&gt; '{"name":"First"}'


You could even use the more specialized operator class jsonb_path_ops. See:


How to get particular object from jsonb array in PostgreSQL?

B-tree expression index on d-&gt;&gt;'email' and test with good old =:

CREATE INDEX idx_jsonthings_d_email ON jsonthings ((d-&gt;&gt;'email'));

SELECT d FROM jsonthings WHERE d-&gt;&gt;'email' = 'First';



The second index would be considerably smaller and the query faster.