4

我正在尝试选择列中的roles属性json包含任何值的所有列。

我试过的陈述:

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)它只会拉后面的行,因为它没有检查每个数组元素......

我有以下表components 结构数据

+====+========================================================================================================================================================================================================+==+
| 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属性中的值查询行?

4

4 回答 4

8

表达方式

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')
于 2017-05-31T20:41:23.597 回答
4

https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-overlaps

JSON_OVERLAPS(json_doc1, json_doc2)

比较两个 JSON 文档。如果两个文档有任何共同的键值对或数组元素,则返回 true (1)。如果两个参数都是标量,则函数执行简单的相等测试。

此函数作为 的对应函数JSON_CONTAINS(),它要求搜索到的数组的所有元素都存在于搜索到的数组中。因此,JSON_CONTAINS()对搜索键执行 AND 操作,同时JSON_OVERLAPS()执行 OR 操作。

在 WHERE 子句中使用的 InnoDB 表的 JSON 列的查询JSON_OVERLAPS()可以使用多值索引进行优化。多值索引,提供详细信息和示例。

比较两个数组时,JSON_OVERLAPS()如果它们共享一个或多个数组元素,则返回 true,否则返回 false。

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)
于 2020-07-08T13:02:47.977 回答
0

尝试其中一种,它应该可以工作

SELECT * FROM components WHERE JSON_CONTAINS([1],  roles, '$');

SELECT * FROM components WHERE JSON_CONTAINS([1],  CAST(roles as JSON), '$');
于 2020-07-27T03:54:33.073 回答
0

刚刚尝试过,因为我遇到了类似的问题,以下对我有用:

field->'$.sub' REGEXP '^(1|3|5)$'

是的,这里似乎可以使用正则表达式...

请注意,如果您尝试查询 json 中的字符串字段,则应考虑字符串被 a 包围",因此您必须查询如下内容:

customer->'$.mail' REGEXP '^\"(info|contact)@.*\.com\"$'

希望它有所帮助,但我不知道这对性能有何影响......

于 2022-02-03T14:45:12.553 回答