JSON_HASH
Описание
JSON_HASH вычисляет хеш-значение объекта JSON. Эта функция принимает параметр типа JSON и возвращает хеш-значение типа BIGINT.
Перед вычислением хеш-значения функция сортирует ключи объекта JSON. Благодаря этому объекты JSON с одинаковым содержимым, но разным порядком ключей получают одинаковое хеш-значение.
Синтаксис
JSON_HASH(json_value)
Псевдоним
JSONB_HASH
Параметры
json_value - Значение JSON, для которого нужно вычислить хеш-значение. Должно иметь тип JSON.
Возвращаемое значение
Возвращает хеш-значение типа BIGINT.
Если входное значение равно NULL, функция возвращает NULL.
Использование
Стандарт JSON определяет, что пары ключ-значение в объектах JSON не упорядочены. Чтобы объекты JSON с одинаковым содержимым однозначно идентифицировались в разных системах, функция JSON_HASH сортирует пары ключ-значение перед вычислением хеш-значения, аналогично вызову функции SORT_JSON_OBJECT_KEYS.
Кроме того, хотя Doris допускает повторяющиеся ключи в объектах JSON, при вычислении хеша учитывается только первая пара ключ-значение для каждого ключа. Такое поведение лучше соответствует практическим сценариям использования.
Примеры
- Базовое вычисление хеша
SELECT json_hash(cast('123' as json));
+--------------------------------+
| json_hash(cast('123' as json)) |
+--------------------------------+
| 5279066513252500087 |
+--------------------------------+
- Проверка функции-псевдонима
SELECT json_hash(cast('123' as json)), jsonb_hash(cast('123' as json));
+--------------------------------+---------------------------------+
| json_hash(cast('123' as json)) | jsonb_hash(cast('123' as json)) |
+--------------------------------+---------------------------------+
| 5279066513252500087 | 5279066513252500087 |
+--------------------------------+---------------------------------+
Как видно из результата, функции json_hash и jsonb_hash возвращают одинаковые хеш-значения для одинаковых входных данных, что подтверждает их эквивалентность.
- Проверка сортировки ключей
SELECT
json_hash(cast('{"a":123, "b":456}' as json)),
json_hash(cast('{"b":456, "a":123}' as json));
+-----------------------------------------------+-----------------------------------------------+
| json_hash(cast('{"a":123, "b":456}' as json)) | json_hash(cast('{"b":456, "a":123}' as json)) |
+-----------------------------------------------+-----------------------------------------------+
| 82454694884268544 | 82454694884268544 |
+-----------------------------------------------+-----------------------------------------------+
Функция json_hash возвращает одинаковое хеш-значение независимо от порядка ключей, поскольку сортирует их перед вычислением хеша.
- Обработка повторяющихся ключей
SELECT
json_hash(cast('{"a":123}' as json)),
json_hash(cast('{"a":456}' as json)),
json_hash(cast('{"a":123, "a":456}' as json));
+--------------------------------------+--------------------------------------+-----------------------------------------------+
| json_hash(cast('{"a":123}' as json)) | json_hash(cast('{"a":456}' as json)) | json_hash(cast('{"a":123, "a":456}' as json)) |
+--------------------------------------+--------------------------------------+-----------------------------------------------+
| -7416836614234106918 | -3126362109586887012 | -7416836614234106918 |
+--------------------------------------+--------------------------------------+-----------------------------------------------+
Если объект JSON содержит повторяющиеся ключи ({"a":123, "a":456}), функция json_hash учитывает при вычислении хеша только первую пару ключ-значение. Как видно из результата, хеш-значение объекта JSON с повторяющимися ключами совпадает с хеш-значением объекта, содержащего только первую пару ключ-значение {"a":123}.
- Обработка чисел разных типов
SELECT
json_hash(to_json(cast('123' as int))),
json_hash(to_json(cast('123' as tinyint)));
+----------------------------------------+--------------------------------------------+
| json_hash(to_json(cast('123' as int))) | json_hash(to_json(cast('123' as tinyint))) |
+----------------------------------------+--------------------------------------------+
| 7882559133986259892 | 5279066513252500087 |
+----------------------------------------+--------------------------------------------+
Одно и то же числовое значение 123, сохранённое в JSON с разными типами (int и tinyint), даёт разные хеш-значения. Это связано с тем, что реализация JSON в Doris сохраняет информацию о типах, а при вычислении хеша эти различия учитываются.
- Использование normalize_json_numbers_to_double для приведения к единому типу
SELECT
json_hash(normalize_json_numbers_to_double(to_json(cast('123' as int)))),
json_hash(normalize_json_numbers_to_double(to_json(cast('123' as tinyint))));
+--------------------------------------------------------------------------+------------------------------------------------------------------------------+
| json_hash(normalize_json_numbers_to_double(to_json(cast('123' as int)))) | json_hash(normalize_json_numbers_to_double(to_json(cast('123' as tinyint)))) |
+--------------------------------------------------------------------------+------------------------------------------------------------------------------+
| 4028523408277343359 | 4028523408277343359 |
+--------------------------------------------------------------------------+------------------------------------------------------------------------------+
Этот пример показывает, как решить описанную выше проблему: сначала преобразовать все числовые значения в тип с плавающей точкой двойной точности с помощью функции normalize_json_numbers_to_double, а затем вычислить хеш-значение. Это обеспечивает одинаковые хеш-значения независимо от исходного числового типа.
- Обработка значений NULL
SELECT json_hash(null);
+-----------------+
| json_hash(null) |
+-----------------+
| NULL |
+-----------------+
Примечания
-
У функции
JSON_HASHесть псевдонимJSONB_HASH; обе функции работают одинаково. -
Эта функция сортирует ключи объектов JSON перед вычислением хеш-значений, аналогично вызову функции
SORT_JSON_OBJECT_KEYS. -
Для повторяющихся ключей в объектах JSON функция учитывает при вычислении хеша только первую пару ключ-значение.
-
Поскольку JSON в Doris может хранить числа разных типов (int, tinyint, bigint, float, double, decimal), одно и то же числовое значение с разными типами может давать разные хеш-значения. Если требуется согласованность, перед вычислением хеш-значений можно преобразовать все числовые значения к единому типу с помощью функции
NORMALIZE_JSON_NUMBERS_TO_DOUBLE. -
При создании объектов JSON путём разбора текста (например, при использовании
CASTдля преобразования строки в JSON) Doris автоматически выбирает подходящий числовой тип для хранения, поэтому обычно беспокоиться о несогласованности числовых типов не требуется. -
Обратите внимание: если вы не преобразуете "123" в объект JSON вручную с помощью
cast/to_json, а используете преобразование из текста (разбор объектов JSON из строк), Doris сохранит "123" только как объект JSON типа tinyint, и ситуации, когда "123" хранится одновременно как int и tinyint, не возникнет.