У меня есть таблица, содержащая все продукты. Свойства продукта хранятся в поле JSON, называемом свойствами. Внутри объекта JSON у меня есть свойство для хранения путей изображения продукта. Структура выглядит так:
{..., "images": [{"original": "path/to/original", "icon": "path/to/icon", "small": "path/to/small"}, {"original": "path/to/original"}], ...}
Поскольку вы можете видеть, что второе изображение не имеет размеров, отличных от исходного, мое приложение должно создавать разные размеры этого изображения. Проблема в том, что я не могу фильтровать такие записи, которые не имеют свойств "маленький" или "значок" (или любого произвольного размера) в одном из массивов элементов в изображениях. Я попробовал следующее условие WHERE:
... WHERE JSON_CONTAINS_PATH(properties, 'one', '$.images') AND JSON_CONTAINS_PATH(properties, 'all', '$.images[*].icon', '$.images[*].small') = 0;
К сожалению, это не сработает. В моем понимании второй JSON_CONTAINS_PATH должен искать записи, которые пропускают значок или небольшое свойство в любом из элементов массива изображений. Ясно, что это не так.
Какую функцию JSON использовать? (если JSON_CONTAINS_PATH не подходит для этой цели) Что нужно изменить в запросе? (если это)
Мне удалось решить мою проблему, используя два разных запроса:
Сначала я пытаюсь определить максимальное количество изображений, загруженных для продукта:
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');
И тогда я формирую условия, основанные на этом числе:
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);
(Это для четырех изображений.)
Я не уверен, что здесь происходит, но я не могу воссоздать вашу проблему.
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 (свойства, "все", "$. images [*]. icon") сами по себе и json_contains_path (свойства, "все", "$. images.small") сами по себе работают.
Поэтому я знаю, что найденные записи находятся. Чтобы получить "нет соответствия", мне нужна запись, которая не соответствует. Я собираюсь УБИТЬ это, чтобы новая запись не имела "малого" объекта в массиве изображений.
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)
Я получаю аналогичные результаты тестирования для "значка". Поэтому я не уверен, что не работает для вас.