How to create index on json column in MySQL?
Asked Answered
D

3

20

How to create index on sub-documents in Json data type in MySQL server?

I know we have to create a generated column from the base table and then need to index that column Virtually or stored.

But I want syntax for creating a generated column for sub-document.

Deformation answered 15/7, 2016 at 6:18 Comment(0)
M
22

For indexing values stored in JSON, use a stored generated column.

For example, to index title and category of

{"title": "Some Title", "category": "Some Category", "url": "...", ...}

use something like:

CREATE TABLE listings (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  title VARCHAR(255) AS
    (data->>'$.title') STORED,
  category VARCHAR(255) AS
    (data->>'$.category') STORED,
  data JSON NOT NULL,
  KEY (title),           -- index title
  KEY (category),        -- index category
  KEY (title, category)  -- composite index of title & category
);

Read more about it in my article MySQL as smart JSON storage :-)

Mccaslin answered 11/7, 2020 at 12:26 Comment(0)
H
21

With MySQL 8.0.21 release it is possible to use this syntax:

CREATE TABLE inventory(
items JSON,
INDEX i1 ( (JSON_VALUE(items, '$.name' RETURNING CHAR(50))) ),
INDEX i2 ( (JSON_VALUE(items, '$.price' RETURNING DECIMAL(5,2))) ),
INDEX i3 ( (JSON_VALUE(items, '$.quantity' RETURNING UNSIGNED)) )
);

and query using:

SELECT items->"$.price" FROM inventory
WHERE JSON_VALUE(items, '$.name' RETURNING VARCHAR(50)) = "hat";

SELECT * FROM inventory
WHERE JSON_VALUE(items, '$.price' RETURNING DECIMAL(5,2)) <= 100.01;

SELECT items->"$.name" AS item, items->"$.price" AS amount
FROM inventory
WHERE JSON_VALUE(items, '$.quantity' RETURNING UNSIGNED) > 500;

source: https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-21.html

Herwick answered 8/3, 2021 at 14:57 Comment(2)
This looks like a very valid answer, I don't see why it's downvoted without a comment. the release notes doesn't help that much either. It says it's equivalent to calling CAST( JSON_UNQUOTE( JSON_EXTRACT(json_doc, path) ) AS type) but I don't think I can do a INDEX i1 ( CAST( JSON_UNQUOTE( JSON_EXTRACT(json_doc, path) ) AS type) ). Idk. All these questions because I am too lazy to spin up a test environment.Yates
Allright. I tested it out and found out that it doesn't work which is not @NeverEndingQueue's fault. Mysal documentation has an error JSON_VALUE does not accept VARCHAR should be changed to CHAR. For differences between the two: dev.mysql.com/doc/refman/8.0/en/char.htmlYates
S
10

JSON columns, like columns of other binary types, are not indexed directly; instead, you can create an index on a generated column that extracts a scalar value from the JSON column. See Section “Secondary Indexes and Generated Virtual Columns”, for a detailed example.

Si answered 15/7, 2016 at 6:56 Comment(1)
See also : mysqlserverteam.com/indexing-json-documents-via-virtual-columnsCamisole

© 2022 - 2024 — McMap. All rights reserved.