"bar"}'::jsonb ? 'foo';
-- Object values are not considered:
SELECT '{"foo": "bar"}'::jsonb ? 'bar'; -- yields false
-- As with containment, existence must match at the top level:
SELECT '{"foo": {"bar": "baz"}}'::jsonb ? 'bar'; -- yields false
-- A string is considered to exist if it matches a primitive JSON string:
SELECT '"foo"'::jsonb ? 'foo';
</programlisting>
<para>
JSON objects are better suited than arrays for testing containment or
existence when there are many keys or elements involved, because
unlike arrays they are internally optimized for searching, and do not
need to be searched linearly.
</para>
<tip>
<para>
Because JSON containment is nested, an appropriate query can skip
explicit selection of sub-objects. As an example, suppose that we have
a <structfield>doc</structfield> column containing objects at the top level, with
most objects containing <literal>tags</literal> fields that contain arrays of
sub-objects. This query finds entries in which sub-objects containing
both <literal>"term":"paris"</literal> and <literal>"term":"food"</literal> appear,
while ignoring any such keys outside the <literal>tags</literal> array:
<programlisting>
SELECT doc->'site_name' FROM websites
WHERE doc @> '{"tags":[{"term":"paris"}, {"term":"food"}]}';
</programlisting>
One could accomplish the same thing with, say,
<programlisting>
SELECT doc->'site_name' FROM websites
WHERE doc->'tags' @> '[{"term":"paris"}, {"term":"food"}]';
</programlisting>
but that approach is less flexible, and often less efficient as well.
</para>
<para>
On the other hand, the JSON existence operator is not nested: it will
only look for the specified key or array element at top level of the
JSON value.
</para>
</tip>
<para>
The various containment and existence operators, along with all other
JSON operators and functions are documented
in <xref linkend="functions-json"/>.
</para>
</sect2>
<sect2 id="json-indexing">
<title><type>jsonb</type> Indexing</title>
<indexterm>
<primary>jsonb</primary>
<secondary>indexes on</secondary>
</indexterm>
<para>
GIN indexes can be used to efficiently search for
keys or key/value pairs occurring within a large number of
<type>jsonb</type> documents (datums).
Two GIN <quote>operator classes</quote> are provided, offering different
performance and flexibility trade-offs.
</para>
<para>
The default GIN operator class for <type>jsonb</type> supports queries with
the key-exists operators <literal>?</literal>, <literal>?|</literal>
and <literal>?&</literal>, the containment operator
<literal>@></literal>, and the <type>jsonpath</type> match
operators <literal>@?</literal> and <literal>@@</literal>.
(For details of the semantics that these operators
implement, see <xref linkend="functions-jsonb-op-table"/>.)
An example of creating an index with this operator class is:
<programlisting>
CREATE INDEX idxgin ON api USING GIN (jdoc);
</programlisting>
The non-default GIN operator class <literal>jsonb_path_ops</literal>
does not support the key-exists operators, but it does support
<literal>@></literal>, <literal>@?</literal> and <literal>@@</literal>.
An example of creating an index with this operator class is:
<programlisting>
CREATE INDEX idxginp ON api USING GIN (jdoc jsonb_path_ops);
</programlisting>
</para>
<para>
Consider the example of a table that stores JSON documents
retrieved from a third-party web service, with a documented schema
definition. A typical document is:
<programlisting>
{
"guid": "9c36adc1-7fb5-4d5b-83b4-90356a46061a",
"name": "Angela Barton",
"is_active": true,
"company": "Magnafone",
"address": "178 Howard Place, Gulf, Washington, 702",
"registered": "2009-11-07T08:53:22 +08:00",
"latitude": 19.793713,
"longitude": 86.513373,