MySQL JSON - 使用 IN 语句 | json_contains
MySQL JSON - using IN statement | json_contains
我正在尝试 select json
列中 roles
属性 包含任何值的所有列。
我试过的语句:
SELECT * FROM components WHERE json->'$.roles' IN(1)
- 这甚至行不通,但我认为应该...
SELECT * FROM components WHERE JSON_CONTAINS(components, '1', '$.roles')
- 这确实有效,但是很严格,所以当我使用
1
时,它会像应该的那样拉动两者,因为它们都包含 1,但是如果我插入 1,2
或 JSON_ARRAY(1,2)
它将只拉后面的行,因为它不检查每个数组元素...
我有以下tablecomponents
结构和数据:
+====+========================================================================================================================================================================================================+==+
| id | json | |
+====+========================================================================================================================================================================================================+==+
| 1 | {"area": 1, "roles": [1], "elements": [{"home": {"content": "Home", "attributes": {"class": "my_class_1"}}}, {"dashboard": {"content": "Dashboard", "attributes": {"class": "my_class_1"}}}]} | |
+----+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--+
| 2 | {"area": 1, "roles": [1, 2, 5], "elements": [{"home": {"content": "Testing", "attributes": {"class": "my_class_1"}}}, {"dashboard": {"content": "Dashboard", "attributes": {"class": "my_class_1"}}}]} | |
+----+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--+
问题: 我如何修改这些语句中的任何一个以允许它们根据 roles
属性 中的值查询行?
表达式
value in (x, y, z, ...)
相当于
value = x OR value = y OR value = z OR ...
这不适用于像 json->'$.roles'
这样的数组,因为数组不等于它的元素,您需要调用 JSON_CONTAINS()
来测试它。
对于您想要的,您需要为每个要测试的值调用 JSON_CONTAINS()
。
WHERE JSON_CONTAINS(components, '1', '$.roles') OR JSON_CONTAINS(components, '2', '$.roles')
见https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-overlaps
JSON_OVERLAPS(json_doc1, json_doc2)
比较两个 JSON 文档。 Returns true (1) 如果两个文档有任何共同的键值对或数组元素。如果两个参数都是标量,则该函数执行简单的相等性测试。
此函数与JSON_CONTAINS()
相对应,它要求搜索的数组中的所有元素都存在于搜索到的数组中。因此,JSON_CONTAINS()
对搜索键执行AND运算,而 JSON_OVERLAPS()
执行 OR 运算。
在 WHERE 子句中使用 JSON_OVERLAPS()
对 InnoDB 表的 JSON 列的查询可以使用多值索引进行优化。多值索引,提供详细信息和示例。
比较两个数组时,JSON_OVERLAPS()
returns如果它们共享一个或多个数组元素,则为真,否则为假。
mysql> SELECT JSON_OVERLAPS("[1,3,5,7]", "[2,5,7]");
+---------------------------------------+
| JSON_OVERLAPS("[1,3,5,7]", "[2,5,7]") |
+---------------------------------------+
| 1 |
+---------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT JSON_OVERLAPS("[1,3,5,7]", "[2,6,7]");
+---------------------------------------+
| JSON_OVERLAPS("[1,3,5,7]", "[2,6,7]") |
+---------------------------------------+
| 1 |
+---------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT JSON_OVERLAPS("[1,3,5,7]", "[2,6,8]");
+---------------------------------------+
| JSON_OVERLAPS("[1,3,5,7]", "[2,6,8]") |
+---------------------------------------+
| 0 |
+---------------------------------------+
1 row in set (0.00 sec)
尝试其中一种应该有效
SELECT * FROM components WHERE JSON_CONTAINS([1], roles, '$');
SELECT * FROM components WHERE JSON_CONTAINS([1], CAST(roles as JSON), '$');
刚试过,因为我遇到了类似的问题,以下对我有用:
field->'$.sub' REGEXP '^(1|3|5)$'
是的,这里似乎可以使用正则表达式...
请注意,如果您尝试查询 json 中的字符串字段,您应该考虑到字符串被 "
包围,因此您必须这样查询:
customer->'$.mail' REGEXP '^\"(info|contact)@.*\.com\"$'
希望对您有所帮助,但我不知道这对性能有何影响...
我正在尝试 select json
列中 roles
属性 包含任何值的所有列。
我试过的语句:
SELECT * FROM components WHERE json->'$.roles' IN(1)
- 这甚至行不通,但我认为应该...
SELECT * FROM components WHERE JSON_CONTAINS(components, '1', '$.roles')
- 这确实有效,但是很严格,所以当我使用
1
时,它会像应该的那样拉动两者,因为它们都包含 1,但是如果我插入1,2
或JSON_ARRAY(1,2)
它将只拉后面的行,因为它不检查每个数组元素...
我有以下tablecomponents
结构和数据:
+====+========================================================================================================================================================================================================+==+
| id | json | |
+====+========================================================================================================================================================================================================+==+
| 1 | {"area": 1, "roles": [1], "elements": [{"home": {"content": "Home", "attributes": {"class": "my_class_1"}}}, {"dashboard": {"content": "Dashboard", "attributes": {"class": "my_class_1"}}}]} | |
+----+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--+
| 2 | {"area": 1, "roles": [1, 2, 5], "elements": [{"home": {"content": "Testing", "attributes": {"class": "my_class_1"}}}, {"dashboard": {"content": "Dashboard", "attributes": {"class": "my_class_1"}}}]} | |
+----+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--+
问题: 我如何修改这些语句中的任何一个以允许它们根据 roles
属性 中的值查询行?
表达式
value in (x, y, z, ...)
相当于
value = x OR value = y OR value = z OR ...
这不适用于像 json->'$.roles'
这样的数组,因为数组不等于它的元素,您需要调用 JSON_CONTAINS()
来测试它。
对于您想要的,您需要为每个要测试的值调用 JSON_CONTAINS()
。
WHERE JSON_CONTAINS(components, '1', '$.roles') OR JSON_CONTAINS(components, '2', '$.roles')
见https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-overlaps
JSON_OVERLAPS(json_doc1, json_doc2)
比较两个 JSON 文档。 Returns true (1) 如果两个文档有任何共同的键值对或数组元素。如果两个参数都是标量,则该函数执行简单的相等性测试。
此函数与JSON_CONTAINS()
相对应,它要求搜索的数组中的所有元素都存在于搜索到的数组中。因此,JSON_CONTAINS()
对搜索键执行AND运算,而 JSON_OVERLAPS()
执行 OR 运算。
在 WHERE 子句中使用 JSON_OVERLAPS()
对 InnoDB 表的 JSON 列的查询可以使用多值索引进行优化。多值索引,提供详细信息和示例。
比较两个数组时,JSON_OVERLAPS()
returns如果它们共享一个或多个数组元素,则为真,否则为假。
mysql> SELECT JSON_OVERLAPS("[1,3,5,7]", "[2,5,7]");
+---------------------------------------+
| JSON_OVERLAPS("[1,3,5,7]", "[2,5,7]") |
+---------------------------------------+
| 1 |
+---------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT JSON_OVERLAPS("[1,3,5,7]", "[2,6,7]");
+---------------------------------------+
| JSON_OVERLAPS("[1,3,5,7]", "[2,6,7]") |
+---------------------------------------+
| 1 |
+---------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT JSON_OVERLAPS("[1,3,5,7]", "[2,6,8]");
+---------------------------------------+
| JSON_OVERLAPS("[1,3,5,7]", "[2,6,8]") |
+---------------------------------------+
| 0 |
+---------------------------------------+
1 row in set (0.00 sec)
尝试其中一种应该有效
SELECT * FROM components WHERE JSON_CONTAINS([1], roles, '$');
SELECT * FROM components WHERE JSON_CONTAINS([1], CAST(roles as JSON), '$');
刚试过,因为我遇到了类似的问题,以下对我有用:
field->'$.sub' REGEXP '^(1|3|5)$'
是的,这里似乎可以使用正则表达式...
请注意,如果您尝试查询 json 中的字符串字段,您应该考虑到字符串被 "
包围,因此您必须这样查询:
customer->'$.mail' REGEXP '^\"(info|contact)@.*\.com\"$'
希望对您有所帮助,但我不知道这对性能有何影响...