随着 MySQL 对 JSON 类型的原生支持,操作 JSON 数据已变得非常高效与强大。在过去数年的版本中,MySQL 也在不断地增强 JSON 处理相关的功能。在 JSON 处理中需要非常频繁的使用“JSON Path” 语法,而这部分又是略微复杂的部分,本文将系统的介绍如何在 MySQL 中使用 JSON Path,包括语法规则、各种通配符用法、递归匹配等高级技巧,并通过丰富示例帮助开发者快速掌握。
JSON Path 是一种表示法,用来描述如何在 JSON 文档中定位数据。类似于文件系统路径,JSON Path 指引着从 JSON 根节点出发,逐步深入结构内部。在 MySQL 中,几乎所有的 JSON
相关的函数都会使用到,包括:JSON_EXTRACT()
、JSON_SET()
、JSON_REPLACE()
、JSON_REMOVE()
、JSON_CONTAINS()
等。
我们看到的场景的写法类似于:$.name
、$.colors[0]
、$.store**.price
等。
JSON Path
的基础语法,遵循以下规则:
$
:表示 JSON 文档的根节点。.
:用于访问对象中的属性。["key"]
:另一种访问对象属性的方式,适合处理特殊字符的 key。[index]
:访问数组中的元素。*
:通配符,匹配所有子元素。**
:递归通配符,匹配所有嵌套层级的元素[start to end]
:数组范围选择创建带 JSON
字段的表,并写入数据:
CREATE TABLE t1 (
id INT PRIMARY KEY AUTO_INCREMENT,
data JSON
);
INSERT INTO t1 (data) VALUES
('{
"name": "Alice",
"age": 25,
"email": "alice@example.com"
}');
这里使用基本的$.name
引用根节点中属性为name
的对象,示例如下:
mysql> SELECT JSON_EXTRACT(data, '$.name') FROM t1;
+------------------------------+
| JSON_EXTRACT(data, '$.name') |
+------------------------------+
| "Alice" |
+------------------------------+
1 row in set (0.00 sec)
也可以使用如下等价的写法data->'$.name'
:
mysql> SELECT data->'$.name' FROM t1;
+----------------+
| data->'$.name' |
+----------------+
| "Alice" |
+----------------+
初始化如下数据:
-- truncate table t1;
INSERT INTO t1 (data) VALUES
('{
"colors": ["red", "green", "blue"]
}');
先访问colors
属性,再查找该数组对象的第一个元素(注意:编号是0),故 JSON Path
为$.colors[0]
,示例如下:
mysql> SELECT data->'$.colors[0]' AS first_color FROM t1;
+-------------+
| first_color |
+-------------+
| "red" |
+-------------+
除了像上述展示的,可以使用数值访问数组外,还可以使用0 to 1
这样的语法表示一个范围,并访问数组中的多个元素:
mysql> SELECT data->'$.colors[0 to 1]' AS first_color FROM t1;
+------------------+
| first_color |
+------------------+
| ["red", "green"] |
+------------------+
mysql> SELECT data->'$.colors[1 to 1]' AS first_color FROM t1;
+-------------+
| ["green"] |
+-------------+
mysql> SELECT data->'$.colors[1 to 2]' AS first_color FROM t1;
+-------------------+
| ["green", "blue"] |
+-------------------+
为了展示相关的示例,这里先给出一个更为复杂的示例数据:
CREATE TABLE t1 (
id INT PRIMARY KEY AUTO_INCREMENT,
data JSON
);
-- truncate table t1;
INSERT INTO t1 (data) VALUES
('{
"store": {
"book": [
{
"category": "fiction",
"title": "Harry Potter",
"price": 29.99
},
{
"category": "fiction",
"title": "Lord of the Rings",
"price": 49.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}');
则可以使用如下的搜索表达式:$.store.book[*]
:
SELECT data->'$.store.book[*]' AS all_books
FROM t1;
mysql> SELECT data->'$.store.book[*]' AS all_books
-> FROM t1;
+--------------------------------------------------------------+
| all_books |
+--------------------------------------------------------------+
| [{"price": 29.99, "title"...}, {"price": 49.99, "title"...}] |
+--------------------------------------------------------------+
这里比较容易错误的写成:$.store.book.*
、$.store.book.[*]
或$.store.book*
。
依旧使用上述的数据,这里可以使用递归的通配符(**
)查询结构中所有title
属性的取值,则'$.store**.title'
:
SELECT data->'$.store**.title' AS all_books
FROM t1;
+---------------------------------------+
| all_books |
+---------------------------------------+
| ["Harry Potter", "Lord of the Rings"] |
+---------------------------------------+
当然,也可以改成直接从“根”处开始递归查找,即$**.title
mysql> SELECT data->'$**.title' AS all_books FROM t1;
+---------------------------------------+
| all_books |
+---------------------------------------+
| ["Harry Potter", "Lord of the Rings"] |
+---------------------------------------+
类似的,我们还可以取出所有的价格:
SELECT
data->'$.store**.price' AS book_prices
FROM t1;
+-----------------------+
| book_prices |
+-----------------------+
| [29.99, 49.99, 19.95] |
+-----------------------+
熟悉 MySQL JSON Path Syntax 可以让开发者更加高效操作 JSON 数据。更多参考: