30.9 Using a Multivalue Function-Based Index
A json_exists
query in a WHERE
clause can
pick up a multivalue function-based index if (and only if) the data that it targets matches
the scalar types specified in the index.
A multivalue function-based index for SQL/JSON condition
json_exists
targets scalar JSON values, either individually or
as elements of a JSON array. You can define a multivalue index only for JSON data
that is stored as JSON
data type.
Condition json_exists
returns true if the data it
targets matches the SQL/JSON path expression (or equivalent simple dot-notation
syntax) in the query. Otherwise it returns false. It is common for the path
expression to include a filter expression — matching then requires that the targeted
data satisfy that filter.
A multivalue index that is defined using a data-type conversion item
method (such as numberOnly()
) that has "only" in its name can be
picked up only by json_exists
queries that also use that same item
method. That is, the query must use the same item method explicitly. See
Creating Multivalue Function-Based Indexes for JSON_EXISTS for more information.
A multivalue index defined using no item method, or using a data-type
conversion item method (such as number()
) that does not have
"only" in its name, can be picked up by a query that targets a scalar value
(possibly as an array element) that can be converted to the type indicated by
the item method. See SQL/JSON Path Expression Item Methods for information about the data-type conversion item methods.
The examples here use SQL/JSON condition json_exists
in
a WHERE
clause to check for a subparts
field value
that matches 730
. They are discussed in terms of whether they can
pick up multivalue indexes mvi
, cmvi_1
, and
cmvi_2
, which are defined in Creating Multivalue Function-Based Indexes for JSON_EXISTS. Conversion of JSON scalar values to SQL scalar values is specified in Table 18-2.
Example 30-17 JSON_EXISTS Query With Item Method numberOnly()
This example uses item method numberOnly()
in a
WHERE
clause. The query can pick up index mvi
when the path expression targets either a numeric
subparts
value of 730
(e.g. subparts :
730
) or an array subparts
value with one or more
numeric elements of 730
(e.g. subparts:[630,
730, 690, 730]
). It cannot pick up index mvi
for targeted string values of "730"
(e.g.
subparts:"730"
or subparts:["630", "730", 690,
"730"]
).
If index mvi
had instead been defined used item method
number()
, then this query could pick up the index for a numeric
subparts
value of 730
, a string
subparts
value of "730"
, or an array
subparts
value with numeric elements of 730
or
string elements of "730"
.
SELECT count(*) FROM parts_tab
WHERE json_exists(jparts, '$.parts.subparts?(@.numberOnly() == 730)');
Example 30-18 JSON_EXISTS Query Without Item Method numberOnly()
These two queries do not use item method
numberOnly()
. The first uses method number()
,
which converts the targeted data to a number, if possible. The second does no type
conversion of the targeted data.
Index mvi
cannot be picked up by either of these queries, even if the targeted data is
the number 730
. For the index to be picked up, a query must
use numberOnly()
, because the index is defined using
numberOnly()
.
SELECT count(*) FROM parts_tab t
WHERE json_exists(jparts, '$.parts.subparts?(@.number() == 730)');
SELECT count(*) FROM parts_tab t
WHERE json_exists(jparts, '$.parts.subparts?(@ == 730)');
Example 30-19 JSON_EXISTS Query Checking Multiple Fields
The filter expression in this query specifies the existence of a
partno
field that matches the SQL NUMBER
value
4
(possibly by conversion from a JSON string), and a field
subparts
that matches the number 730
.
The query can pick up either of the indexes cmvi_1
or
cmvi_2
. Both rows of the data match these indexes, because each
row has a parts.partno
value that matches the number
4
and a parts.subparts
value that matches the
number 730
. For the subparts
match, the first row
has a subparts
value of 730
, and the second row
has a subparts
value that is an array with a value of
730
.
SELECT a FROM parts_tab
WHERE json_exists(jparts,'$.parts[*]?(@.partno == 4 &&
@.subparts == 730)');
Example 30-20 JSON_EXISTS Query Checking Array Element Position
This example is similar to Example 30-19, but in addition to requiring that field partno
match the number 4
, the filter expression here requires that the
value of field subparts
match an array of at least two
elements, and that the second element of the array match the number
730
.
This query can pick up index cmvi_2
, including for
positional predicate [1]
. Index cmvi_2
specifies
virtual column subpartNum
, which corresponds to JSON field
subparts
, as the penultimate column, just before the final,
FOR ORDINALITY
, column.
This query could also pick up index cmvi_1
, but that index has no
FOR ORDINALITY
column, so making use of it would require an
extra step, to evaluate the array-position condition, [1]
. Using
index cmvi_2
requires no such extra step, so it is more performant
for such queries.
SELECT a FROM parts_tab
WHERE json_exists(jparts,'$.parts[*]?(@.partno == 4 &&
@.subparts[1] == 730)');