Home Explore Blog CI



postgresql

7th chunk of `doc/src/sgml/json.sgml`
ea3b8e04b2c6cdcd99482db17da8a26a63b34232ace489060000000100000fb0
 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>@&gt;</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,
    "tags": [
        "enim",
        "aliquip",
        "qui"
    ]
}
</programlisting>
    We store these documents in a table named <structname>api</structname>,
    in a <type>jsonb</type> column named <structfield>jdoc</structfield>.
    If a GIN index is created on this column,
    queries like the following can make use of the index:
<programlisting>
-- Find documents in which the key "company" has value "Magnafone"
SELECT jdoc-&gt;'guid', jdoc-&gt;'name' FROM api WHERE jdoc @&gt; '{"company": "Magnafone"}';
</programlisting>
    However, the index could not be used for queries like the
    following, because though the operator <literal>?</literal> is indexable,
    it is not applied directly to the indexed column <structfield>jdoc</structfield>:
<programlisting>
-- Find documents in which the key "tags" contains key or array element "qui"
SELECT jdoc-&gt;'guid', jdoc-&gt;'name' FROM api WHERE jdoc -&gt; 'tags' ? 'qui';
</programlisting>
    Still, with appropriate use of expression indexes, the above
    query can use an index.  If querying for particular items within
    the <literal>"tags"</literal> key is common, defining an index like this
    may be worthwhile:
<programlisting>
CREATE INDEX idxgintags ON api USING GIN ((jdoc -&gt; 'tags'));
</programlisting>
    Now, the <literal>WHERE</literal> clause <literal>jdoc -&gt; 'tags' ? 'qui'</literal>
    will be recognized as an application of the indexable
    operator <literal>?</literal> to the indexed
    expression <literal>jdoc -&gt; 'tags'</literal>.
    (More information on expression indexes can be found in <xref
    linkend="indexes-expressional"/>.)
  </para>

  <para>
    Another approach to querying is to exploit containment, for example:
<programlisting>
-- Find documents in which the key "tags" contains array element "qui"
SELECT jdoc-&gt;'guid', jdoc-&gt;'name' FROM api WHERE jdoc @&gt; '{"tags": ["qui"]}';
</programlisting>
    A simple GIN index on the <structfield>jdoc</structfield> column can support this
    query.  But note that such an index will store copies of every key and
    value in the <structfield>jdoc</structfield> column, whereas the expression index
    of the previous example stores only data found under
    the <literal>tags</literal> key.  While the simple-index approach is far more
    flexible (since it supports queries about any key), targeted expression
    indexes are likely to be smaller and faster to search than a simple
    index.
  </para>

  <para>
    GIN indexes also support the <literal>@?</literal>
    and <literal>@@</literal> operators, which
    perform <type>jsonpath</type> matching.  Examples are
<programlisting>
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @? '$.tags[*] ? (@ == "qui")';
</programlisting>
<programlisting>
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @@ '$.tags[*] == "qui"';
</programlisting>
    For these operators, a GIN index extracts clauses of the form
    <literal><replaceable>accessors_chain</replaceable>

Title: Querying JSONB Data with GIN Indexes
Summary
GIN indexes can be used to efficiently query JSONB data in PostgreSQL, supporting key-exists, containment, and jsonpath match operations, with examples demonstrating how to create indexes, optimize queries, and use expression indexes to improve query performance for specific use cases.