Возможности JSON_TABLE
Небольшая добавка ко вчерашнему посту. Приведу пример, очень близкий к реальности.
Предположим, есть пользователи, они совершают заказы. Каждый заказ состоит из позиций. У позиции есть стоимость и код валюты. Одна позиция может быть в евро, вторая в долларах и так далее.
Задача в том, чтобы собрать из микросервисов нужных пользователей с заказами и позициями и составить табицу: пользователь, заказ, сумма позиций в евро. Для конвертации валют использовать таблицу коэффициентов.
Вот что получается на практике. Вы идете в микросервис А и получаете джейсончик как на первой картинке:
Потом идете в микросервис В, чтобы получить курсы валют:
Из этих данных вам предстоит слепить конфету. Имейте в виду, что на картинах — лишь малые подмножества данных. В реальности и полей, и вложенных сущностей больше.
Первая беда в том, что данные вложены, и с ними нельзя нормально работать. Я уже
сто раз писал об этом: когда у вас мапа с вектором мап с вектором мап с вектором
мап, ни о каком удобстве не может быть и речи. Код, который обходит такое
дерево, поддерживать невозможно, неважно Питон это или Кложа. В первом случае
это будет императивный быдлокод, во втором — функциональный. Это когда код —
цепочка из десяти вызовов map/mapcat/reduce/group-by
.
В Кложе есть макрос for
для декартовых произведений, но для каждого дерева
нужно писать свою логику. Универсальный вариант я пока не придумал.
Вот как сделать то же самое в SQL. Загоняем оба джейсона в базу. Теперь плющим
первый функцией JSON_TABLE
:
Получаем таблицу users
. Все плоско и декларативно. Обратите внимание на
суррогатные поля order_i
и pos_i
— номера мап в массивах. Это значит, если я
захочу свернуть таблицу обратно в дерево, не будет никаких проблем.
Теперь плющу курсы валют:
Потом присоединяю слева к юзерам курсы валют по их названиям. Это значит, каждая позиция получит коэфициент ее валюты:
И последний шаг: считаю сумму price_eur
с группировкой по пользователю и
заказу.
Готово. Самое важное: все декларативно и без циклов, без присваиваний и аккумуляции списков. Среда, что выполняет этот код, написана на чистом Си и многократно протестирована. Что еще нужно?
Все это можно уместить в один запрос, но я специально расписал по шагам.
Обратите внимание, что в списке валют специально нет одной. Это частая история с микросервисами, когда у них неполные данные. В результате запрос не упадет с NPE, как упал бы ваш Питон или Джава. Просто результат будет NULL, и на посчете суммы это никак не скажется.
Предлагаю вам написать то же самое на своем языке и посмотреть, что получится. Только учтите, что вложенность может быть еще глубже, а данных больше.
Нашли ошибку? Выделите мышкой и нажмите Ctrl/⌘+Enter