Thanks for your answer, it got me thinking about writing a function to extract the product ids and use it in an index. Here's the current result:
CREATE OR REPLACE FUNCTION product_ids(products json) RETURNS integer[] AS $$
select array_agg(value#>>'{id}')::integer[] from json_array_elements(products);
$$ LANGUAGE SQL IMMUTABLE;
CREATE index product_ids_index on events_2012_05 USING GIN (product_ids(event->'products'));
This allows me to issue a query like this to know which users have looked at a certain product id
select user_id from events_2012_05 where product_ids(event->'products')@>ARRAY[545932]
resulting in this query plan
QUERY PLAN
-----------------------------------------------------------------------------------------
Bitmap Heap Scan on events_2012_05 (cost=63.55..18103.42 rows=5071 width=4)
Recheck Cond: (product_ids((event -> 'products'::text)) @> '{545932}'::integer[])
-> Bitmap Index Scan on product_ids_index (cost=0.00..62.28 rows=5071 width=0)
Index Cond: (product_ids((event -> 'products'::text)) @> '{545932}'::integer[])
Cheers
raph