Проверка типа поля и наличия пути

Этот рецепт показывает, как 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.