在JSON字段的数组中搜索缺少属性的记录(MySQL)

时间:2018-07-08 18:23:01

标签: mysql json

我有一个包含所有产品的表。产品属性存储在称为属性的JSON字段中。在JSON对象内部,我有一个用于存储产品图片路径的属性。结构如下:

{..., "images": [{"original": "path/to/original", "icon": "path/to/icon", "small": "path/to/small"}, {"original": "path/to/original"}], ...}

如您所见,第二张图片除了原始图片外没有其他尺寸,这意味着我的应用应为此图片创建不同的尺寸。问题是我无法过滤这样的记录,这些记录在图像中元素的数组之一中没有“ small”或“ icon”(或任何任意大小)属性。 我尝试了以下WHERE条件:

... WHERE JSON_CONTAINS_PATH(properties, 'one', '$.images') AND JSON_CONTAINS_PATH(properties, 'all', '$.images[*].icon', '$.images[*].small') = 0;

不幸的是,这行不通。以我的理解,第二个JSON_CONTAINS_PATH应该搜索缺少images数组中任何元素内的icon或small属性的记录。显然不是这样。

要使用哪个JSON函数? (如果JSON_CONTAINS_PATH不适用于此目的)在查询中要进行哪些更改? (如果是)

2 个答案:

答案 0 :(得分:0)

我不确定这是怎么回事,但我无法为您重现问题。

MySQL [localhost+ ssl/stack] SQL> select * from q1 WHERE JSON_CONTAINS_PATH(pro
erties, 'one', '$.images') and JSON_CONTAINS_PATH(properties,'all','$.images[*]
icon','$.images[*].small');
+----+-------------------------------------------------------------------------
--------------------------------------------------------------------------+
| id | properties
                                                                          |
+----+-------------------------------------------------------------------------
--------------------------------------------------------------------------+
|  1 | {"name": "test", "images": [{"icon": "path/to/icon", "small": "path/to/s
all", "original": "path/to/original"}, {"original": "path/to/original"}]} |
+----+-------------------------------------------------------------------------
--------------------------------------------------------------------------+
1 row in set (0.0013 sec)

和json_contains_path(properties,'all','$。images [*]。icon')本身以及json_contains_path(properties,'all','$。images.small')本身起作用。

因此,我知道找到了匹配的记录。要获得“不匹配”,我需要一条不匹配的记录。我将其向下缩小,以使新记录在images数组中没有“小”对象。

MySQL [localhost+ ssl/stack] SQL> insert into q1 (id,properties) values(2,'{"nam
e" : "test2", "images": [{"icon": "path/2/icon", "medium": "path2/icon"}]}');

重新运行查询:

MySQL [localhost+ ssl/stack] SQL> select * from q1 WHERE JSON_CONTAINS_PATH(prop
erties, 'one', '$.images') and JSON_CONTAINS_PATH(properties,'all','$.images[*].
icon','$.images[*].small') = 0;
+----+--------------------------------------------------------------------------
------+
| id | properties
      |
+----+--------------------------------------------------------------------------
------+
|  2 | {"name": "test2", "images": [{"icon": "path/2/icon", "medium": "path2/ico
n"}]} |
+----+--------------------------------------------------------------------------
------+
1 row in set (0.0020 sec)

对于“ icon”,我得到了类似的测试结果。因此,我不确定什么对您不起作用。

答案 1 :(得分:0)

我设法通过使用两个不同的查询来解决我的问题:

首先,我尝试找出为产品上传的图片的最大数量:

select max(json_length(properties, '$.images')) as max_nr_images from products where json_contains_path(properties, 'one', '$.images[0]') group by json_length(properties, '$.images');

然后我根据该数字形成where条件:

select * from products where json_contains_path(properties, 'one', '$.images[0]') and (json_contains_path(properties, 'all', '$.images[0].icon', '$.images[0].small') = 0 or if(json_contains_path(properties, 'one', '$.images[1]'), json_contains_path(properties, 'all', '$.images[1].icon', '$.images[1].small'), 1) = 0 or if(json_contains_path(properties, 'one', '$.images[2]'), json_contains_path(properties, 'all', '$.images[2].icon', '$.images[2].small'), 1) = 0 or if(json_contains_path(properties, 'one', '$.images[3]'), json_contains_path(properties, 'all', '$.images[3].icon', '$.images[3].small'), 1) = 0 or if(json_contains_path(properties, 'one', '$.images[4]'), json_contains_path(properties, 'all', '$.images[4].icon', '$.images[4].small'), 1) = 0);

(这是四个图像。)