Проверка типа поля и наличия пути
Этот рецепт показывает, как JSON-индекс применяется для проверки структуры документов: наличие конкретного пути, тип значения по пути и т. п. Эти задачи часто встречаются при работе с разнородными JSON-документами, когда часть полей опциональна или может иметь разный тип.
Подготовка
CREATE TABLE documents (
id Uint64,
payload JsonDocument,
PRIMARY KEY (id),
INDEX json_idx GLOBAL USING json ON (payload)
);
UPSERT INTO documents (id, payload) VALUES
(1, JsonDocument(@@{"archived": false, "value": 1, "data": [1, 2, 3]}@@)),
(2, JsonDocument(@@{"archived": false, "value": 2, "data": "plain text"}@@)),
(3, JsonDocument(@@{"archived": true, "value": 3, "data": {"nested": true}}@@)),
(4, JsonDocument(@@{"archived": false, "value": null, "meta": "no data field"}@@));
Найти документы, у которых поле содержит массив
Метод JsonPath .type() возвращает строковое имя типа значения по указанному пути. Это позволяет фильтровать документы по типу содержимого:
SELECT id
FROM documents VIEW json_idx
WHERE JSON_VALUE(payload, '$.data.type()' RETURNING Utf8) = "array"u;
В индекс попадает токен пути $.data — метод .type() завершает построение токена пути. Точная проверка строкового значения "array" выполняется пост-фильтром.
Результат:
id
1
Полный список значений, возвращаемых методом .type(), приведён в описании синтаксиса JsonPath.
Найти документы, у которых поле является не пустым массивом
Метод .size() возвращает количество элементов массива (или 1 для скаляра, 0 для отсутствующего пути). В комбинации с фильтром по типу:
SELECT id
FROM documents VIEW json_idx
WHERE JSON_VALUE(payload, '$.data.type()' RETURNING Utf8) = "array"u
AND JSON_VALUE(payload, '$.data.size()' RETURNING Int64) > 0;
Оба фрагмента индексируются по соответствующим путям, а точные значения проверяются пост-фильтром. Результат: id = 1.
Найти документы со значением false или null
Для проверки «значение равно false» или «значение равно null» используйте JsonPath внутри JSON_EXISTS, а не JSON_VALUE(...) IS NULL:
-- Значение поля 'archived' равно false
SELECT id
FROM documents VIEW json_idx
WHERE JSON_EXISTS(payload, '$.archived ? (@ == false)');
-- Значение поля 'value' равно null
SELECT id
FROM documents VIEW json_idx
WHERE JSON_EXISTS(payload, '$.value ? (@ == null)');
В операцию поиска по индексу попадает путь $.archived (или $.value) и значения false или null, соответственно.
Примечание
Указанные выше условия отбирают документы, в которых указанный атрибут явно установлен в значение false или null. Проверку отсутствия атрибута нельзя выполнить с помощью JSON-индекса.
Подробнее
- JSON_EXISTS — что допустимо в выражениях JsonPath.
- JSON_VALUE — что допустимо при извлечении значений.
- JsonPath: методы — список методов (
type,size,keyvalue, ...) и предикатов JsonPath.