single index item would
be created incorporating all three of <literal>foo</literal>, <literal>bar</literal>,
and <literal>baz</literal> into the hash value. Thus a containment query
looking for this structure would result in an extremely specific index
search; but there is no way at all to find out whether <literal>foo</literal>
appears as a key. On the other hand, a <literal>jsonb_ops</literal>
index would create three index items representing <literal>foo</literal>,
<literal>bar</literal>, and <literal>baz</literal> separately; then to do the
containment query, it would look for rows containing all three of
these items. While GIN indexes can perform such an AND search fairly
efficiently, it will still be less specific and slower than the
equivalent <literal>jsonb_path_ops</literal> search, especially if
there are a very large number of rows containing any single one of the
three index items.
</para>
<para>
A disadvantage of the <literal>jsonb_path_ops</literal> approach is
that it produces no index entries for JSON structures not containing
any values, such as <literal>{"a": {}}</literal>. If a search for
documents containing such a structure is requested, it will require a
full-index scan, which is quite slow. <literal>jsonb_path_ops</literal> is
therefore ill-suited for applications that often perform such searches.
</para>
<para>
<type>jsonb</type> also supports <literal>btree</literal> and <literal>hash</literal>
indexes. These are usually useful only if it's important to check
equality of complete JSON documents.
The <literal>btree</literal> ordering for <type>jsonb</type> datums is seldom
of great interest, but for completeness it is:
<synopsis>
<replaceable>Object</replaceable> > <replaceable>Array</replaceable> > <replaceable>Boolean</replaceable> > <replaceable>Number</replaceable> > <replaceable>String</replaceable> > <replaceable>null</replaceable>
<replaceable>Object with n pairs</replaceable> > <replaceable>object with n - 1 pairs</replaceable>
<replaceable>Array with n elements</replaceable> > <replaceable>array with n - 1 elements</replaceable>
</synopsis>
with the exception that (for historical reasons) an empty top level array sorts less than <replaceable>null</replaceable>.
Objects with equal numbers of pairs are compared in the order:
<synopsis>
<replaceable>key-1</replaceable>, <replaceable>value-1</replaceable>, <replaceable>key-2</replaceable> ...
</synopsis>
Note that object keys are compared in their storage order;
in particular, since shorter keys are stored before longer keys, this
can lead to results that might be unintuitive, such as:
<programlisting>
{ "aa": 1, "c": 1} > {"b": 1, "d": 1}
</programlisting>
Similarly, arrays with equal numbers of elements are compared in the
order:
<synopsis>
<replaceable>element-1</replaceable>, <replaceable>element-2</replaceable> ...
</synopsis>
Primitive JSON values are compared using the same
comparison rules as for the underlying
<productname>PostgreSQL</productname> data type. Strings are
compared using the default database collation.
</para>
</sect2>
<sect2 id="jsonb-subscripting">
<title><type>jsonb</type> Subscripting</title>
<para>
The <type>jsonb</type> data type supports array-style subscripting expressions
to extract and modify elements. Nested values can be indicated by chaining
subscripting expressions, following the same rules as the <literal>path</literal>
argument in the <literal>jsonb_set</literal> function. If a <type>jsonb</type>
value is an array, numeric subscripts start at zero, and negative integers count
backwards from the last element of the array. Slice expressions are not supported.
The result of a subscripting expression is always of the jsonb data type.
</para>
<para>
<command>UPDATE</command> statements may use subscripting