Environment
- Mysql 8.0.35
My Situation
I want to get all rows if cancel.cancels[*].cancel_no is exactly "202401215050123". and also I want to use multi value index to optimize the query.
INSERT INTO pay.payment (payment_no, cancel) VALUES ('2024012150200010', '{"cancels": [{"cancel_no": "202401215050123", "amount": 100}, {"cancel_no": "202401215050125", "amount": 200}]}');
What I have tried so far
I started with fresh database.
SELECT VERSION(); -- 8.0.35--
CREATE DATABASE pay;
USE pay;
create table payment
(
payment_no varchar(50) not null
primary key,
cancel json null
);
-- this does not work --
ALTER TABLE payment
ADD INDEX cancel_no_idx ((
CAST(cancel->>"$.cancels[*].cancel_no" as CHAR(255) ARRAY) COLLATE utf8mb4_bin
)) USING BTREE;
-- this works --
ALTER TABLE payment
ADD INDEX cancel_no_idx ((
CAST(cancel->>"$.cancels[*].cancel_no" as CHAR(255) ARRAY)
)) USING BTREE;
-- insert a row --
INSERT INTO pay.payment (payment_no, cancel) VALUES ('2024012150200010', '{"cancels": [{"cancel_no": "202401215050123", "amount": 100}]}');
-- query --
EXPLAIN SELECT cancel FROM payment WHERE JSON_CONTAINS(cancel, '{"cancel_no": "202401215050123"}', '$.cancels');
but the explain result says it's select_type is SIMPLE.
My Question
- How do I make an index for this purpose and see if query is using the index?
- please aware that multiple "cancel" can be in the
cancelsarray. - and also there can be 0 element in
cancelsarray - it doesn't have to be multi value index. I want want an efficient way (possibly index) to query.
How to use multi value index when querying json array in Mysql 8.0.35?
I have asked similar question before, but I only got the answer for cancel[0].
Quick answer
Use this query
And index that you have created
Then
EXPLAINfound possible keysLong answer
Your index that works is good, the issue in in query
The issue is in
SELECTqueryYou are querying for a whole object no just values of
cancel_noand (I guess) MySQL Engine is not trying to check for what keys index exist and for what not, query JSON is already complex.First try to resolve it may look like get all values of the array
But this doesn't work because error says:
To solve it we can try use extract instead and remove
pathargumentThis form only works when
INDEX cancel_no_idxis present, because strings in json is surrounded by quotes("), to make it works in any case make your query argument in double quotes"like this'"202401215050124"'. It can't be solved withJSON_UNQUOTE(so->>will also not work) as it works only onstringnotarray of strings.Using
EXPLAINon this query will show you that index has been found for this query.Another way if to solve it when we know extracted value by
cancel->'$.cancels[*].cancel_no'is an array, is to useMEMBER OFbecause it expected provided argument to be arrayTesting values that I used