Defining a GIN index across two columns/arrays with similar data
Since you want to run the query on metadata->'emails', you need to build the index on that expression:

create index on contacts using gin ((metadata-&gt;'emails'));


Alternatively, you could make the index on metadata itself, and re-formulate the query condition like this:

... OR metadata @&gt; '{"emails":[{"email": "my@email.com"}]}'


In either case, you also need an index on the column "email", to satisfy the other branch of the OR condition.  Then the two indexes will be combined with a BitmapOr operation.

It is possible you could make one index on both columns using some complicated expression index, but that doesn't really seem worthwhile.