Перейти к содержимому
Последнее обновление

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, при вычислении хеша учитывается только первая пара ключ-значение для каждого ключа. Такое поведение лучше соответствует практическим сценариям использования.

Примеры​

  1. Базовое вычисление хеша
SELECT json_hash(cast('123' as json));
+--------------------------------+
| json_hash(cast('123' as json)) |
+--------------------------------+
| 5279066513252500087 |
+--------------------------------+
  1. Проверка функции-псевдонима
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 возвращают одинаковые хеш-значения для одинаковых входных данных, что подтверждает их эквивалентность.

  1. Проверка сортировки ключей
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 возвращает одинаковое хеш-значение независимо от порядка ключей, поскольку сортирует их перед вычислением хеша.

  1. Обработка повторяющихся ключей
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}.

  1. Обработка чисел разных типов
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 сохраняет информацию о типах, а при вычислении хеша эти различия учитываются.

  1. Использование 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, а затем вычислить хеш-значение. Это обеспечивает одинаковые хеш-значения независимо от исходного числового типа.

  1. Обработка значений NULL
SELECT json_hash(null);
+-----------------+
| json_hash(null) |
+-----------------+
| NULL |
+-----------------+

Примечания​

  1. У функции JSON_HASH есть псевдоним JSONB_HASH; обе функции работают одинаково.

  2. Эта функция сортирует ключи объектов JSON перед вычислением хеш-значений, аналогично вызову функции SORT_JSON_OBJECT_KEYS.

  3. Для повторяющихся ключей в объектах JSON функция учитывает при вычислении хеша только первую пару ключ-значение.

  4. Поскольку JSON в Doris может хранить числа разных типов (int, tinyint, bigint, float, double, decimal), одно и то же числовое значение с разными типами может давать разные хеш-значения. Если требуется согласованность, перед вычислением хеш-значений можно преобразовать все числовые значения к единому типу с помощью функции NORMALIZE_JSON_NUMBERS_TO_DOUBLE.

  5. При создании объектов JSON путём разбора текста (например, при использовании CAST для преобразования строки в JSON) Doris автоматически выбирает подходящий числовой тип для хранения, поэтому обычно беспокоиться о несогласованности числовых типов не требуется.

  6. Обратите внимание: если вы не преобразуете "123" в объект JSON вручную с помощью cast/to_json, а используете преобразование из текста (разбор объектов JSON из строк), Doris сохранит "123" только как объект JSON типа tinyint, и ситуации, когда "123" хранится одновременно как int и tinyint, не возникнет.