JDBC API StarterEnterpriseEnterprise +
Java Database Connectivity (JDBC) API для Semantic Layer позволяет пользователям выполнять запросы к метрикам и измерениям с использованием протокола JDBC, а также предоставляет стандартную функциональность работы с метаданными.
JDBC-драйвер — это программный компонент, позволяющий Java-приложению взаимодействовать с платформой данных. Вот дополнительная информация о нашем JDBC API:
- JDBC API для Semantic Layer использует open-source JDBC‑драйвер с протоколом ArrowFlight SQL.
- Вы можете скачать JDBC‑драйвер с Maven.
- Semantic Layer поддерживает ArrowFlight SQL driver версии 12.0.0 и выше.
- Вы можете встроить драйвер в стек своего приложения по мере необходимости и использовать пример проекта от dbt Labs в качестве ориентира.
- Если вы партнёр или пользователь, разрабатывающий собственное (homegrown) приложение, вам потребуется установить корневой сертификат AWS (AWS root CA) в Java Trust. Подробности см. в документации (актуально для Java и JDBC‑вызовов).
Партнёры dbt Labs могут использовать JDBC API для создания интеграций своих инструментов с Semantic Layer.
Использование JDBC API
Если вы пользователь или партнёр dbt и у вас есть доступ к dbt и Semantic Layer, вы можете настроить и протестировать этот API на данных из вашего собственного инстанса, сконфигурировав Semantic Layer и получив корректные параметры JDBC‑подключения, описанные в этом документе.
Вы можете использовать наш JDBC API и с инструментами, у которых нет официальной интеграции с Semantic Layer. Если используемый вами инструмент позволяет писать SQL и либо поддерживает универсальный JDBC‑драйвер (например, DataGrip), либо поддерживает Dremio и использует драйвер ArrowFlightSQL версии 12.0.0 или выше, вы сможете получить доступ к API Semantic Layer.
Дополнительную информацию см. в разделе Get started with the Semantic Layer.
Обратите внимание, что GraphQL API Semantic Layer не поддерживает использование ref для обращения к объектам dbt. Вместо этого необходимо использовать полностью квалифицированное имя таблицы. Если вы используете макросы dbt во время выполнения запроса для расчёта метрик, такие вычисления следует перенести в определения метрик Semantic Layer в виде кода.
Аутентификация
dbt авторизует запросы к API Semantic Layer. Вам необходимо указать Environment ID, Host и service account tokens или personal access tokens.
Параметры подключения
Подключение JDBC требует нескольких различных параметров подключения.
Вот пример строки подключения URL и отдельных компонентов:
jdbc:arrow-flight-sql://semantic-layer.cloud.getdbt.com:443?&environmentId=202339&token=AUTHENTICATION_TOKEN
| Loading table... |
*Примечание — Если вы тестируете локально на инструменте, таком как DataGrip, вам также может потребоваться предоставить следующую переменную в конце или начале URL JDBC &disableCertificateVerification=true.
Запрос метаданных через API
JDBC API Semantic Layer имеет встроенные вызовы для работы с метаданными, которые позволяют пользователю получать информацию о своих метриках и измерениях.
Разверните следующие переключатели для примеров и команд метаданных:
Запрос значений через API
Для запроса значений доступны следующие параметры. Ваш запрос должен содержать либо параметр metric, либо параметр group_by, чтобы считаться валидным.
| Parameter |
metrics | Имя метрики, как определено в вашей конфигурации метрик dbt | metrics=['revenue'] |
| group_by | Имена измерений или сущностей для группировки. Мы требуем ссылки на сущность измерения (кроме основной временной размерности), которая добавляется перед именем измерения с двойным подчеркиванием. | group_by=['user__country', 'metric_time'] |
| grain | Параметр, специфичный для любой временной размерности, изменяющий гранулярность данных по умолчанию для метрики. | group_by=[Dimension('metric_time') grain('week\|day\|month\|quarter\|year')] |
| where | Условие where, позволяющее фильтровать по измерениям и сущностям с использованием параметров. Это принимает список фильтров ИЛИ строку. Входные данные поставляются с объектами Dimension и Entity. Гранулярность требуется, если Dimension является временной размерностью | "{{ where=Dimension('customer__country') }} = 'US')" |
| limit | Ограничение на возвращаемые данные | limit=10 |
|order | Упорядочивание возвращаемых данных по определенному полю | order_by=['order_gross_profit'], используйте - для убывания, или полную нотацию объекта, если объект подвергается операции: order_by=[Metric('order_gross_profit').descending(True)] |
| compile | Если true, возвращает сгенерированный SQL для платформы данных, но не выполняет его | compile=True |
| saved_query | Сохраненный запрос, который вы можете использовать для часто используемых запросов. | select * from {{ semantic_layer.query(saved_query="new_customer_orders" |
Примечание о временных измерениях и metric_time
Вы заметите, что в списке измерений для всех метрик есть измерение под названием metric_time. Metric_time — это зарезервированное ключевое слово для временных измерений агрегации, специфичных для меры. Для любой временной метрики ключевое слово metric_time всегда должно быть доступно для использования в запросах. Это общее измерение для всех метрик в семантическом графе.
Вы можете рассматривать одну метрику или сотни метрик, и если вы группируете по metric_time, это всегда даст вам правильный временной ряд.
Кроме того, при выполнении расчетов гранулярности, которые являются глобальными (не специфичными для конкретного временного измерения), мы рекомендуем всегда работать с metric_time, и вы получите правильный ответ.
Обратите внимание, что metric_time должен быть доступен в дополнение к любым другим временным измерениям, доступным для метрики(ов). В случае, если вы рассматриваете одну метрику (или несколько метрик из одного источника данных), значения в серии для основной временной размерности и metric_time эквивалентны.
Примеры
В следующих разделах приведены примеры того, как выполнять запросы к метрикам с использованием JDBC API:
- Fetch metadata for metrics — Фильтрация или добавление любого SQL-кода вне шаблонного синтаксиса.
- Query common dimensions — Выбор общих измерений для нескольких метрик.
- Query grouped by time — Получение данных о выручке и новых клиентах с группировкой по времени.
- Query with a time grain — Получение нескольких метрик с изменением гранулярности временного измерения.
- Group by categorical dimension — Группировка по категориальному измерению.
- Query only a dimension — Получение полного списка значений для выбранного измерения.
- Query by all dimensions — Выполнение запроса с использованием всех допустимых измерений.
- Query with where filters — Использование параметра
whereдля фильтрации по измерениям и сущностям с помощью параметров. - Query with a limit — Выполнение запроса с использованием
limitилиorder_by. - Query with order by examples — Запрос с использованием
order_by, который принимает простую строку, представляющую Dimension, Metric или Entity. По умолчанию используется сортировка по возрастанию. Для сортировки по убыванию добавьте символ-перед объектом. - Query with compile keyword — Выполнение запроса с использованием ключевого слова
compileдля предварительного просмотра итогового SQL перед выполнением. - Query a saved query — Выполнение запроса с использованием сохранённого запроса с дополнительными параметрами, такими как
limitилиwhere. - Query metric alias — Запрос метрик с использованием алиасов, которые позволяют применять более простые или интуитивно понятные имена вместо полных определений метрик.
- Multi-hop joins — Выполнение запросов через несколько связанных таблиц (multi-hop joins) с использованием аргумента
entity_pathдля указания пути между связанными сущностями.
Вы можете фильтровать/добавлять любой SQL вне синтаксиса шаблонизации. Например, вы можете использовать следующий запрос для получения имени и измерений для метрики:
select name, dimensions from {{
semantic_layer.metrics()
}}
WHERE name='food_order_amount'
Запрос общих измерений
Вы можете выбрать общие измерения для нескольких метрик. Используйте следующий запрос для получения имени и измерений для нескольких метрик:
select * from {{
semantic_layer.dimensions(metrics=['food_order_amount', 'order_gross_profit'])
}}
Запрос с группировкой по времени
Следующий пример запроса использует сокращенный метод для получения дохода и новых клиентов с группировкой по времени:
select * from {{
semantic_layer.query(metrics=['food_order_amount','order_gross_profit'],
group_by=['metric_time'])
}}
Запрос с временной гранулярностью
Используйте следующий пример запроса для получения нескольких метрик с изменением гранулярности временной размерности:
select * from {{
semantic_layer.query(metrics=['food_order_amount', 'order_gross_profit'],
group_by=[Dimension('metric_time').grain('month')])
}}
Группировка по категориальному измерению
Используйте следующий запрос для группировки по категориальному измерению:
select * from {{
semantic_layer.query(metrics=['food_order_amount', 'order_gross_profit'],
group_by=[Dimension('metric_time').grain('month'), 'customer__customer_type'])
}}
Запрос только измерения
В этом случае вы получите полный список значений измерений для выбранного измерения.
select * from {{
semantic_layer.query(group_by=['customer__customer_type'])
}}
Запрос по всем измерениям
Вы можете использовать endpoint semantic_layer.query_with_all_group_bys, чтобы выполнить запрос по всем допустимым измерениям.
select * from {{
semantic_layer.query_with_all_group_bys(metrics =['revenue','orders','food_orders'],
compile= True)
}}
В результате будут возвращены все измерения, которые являются допустимыми для набора метрик, указанных в запросе.
Запрос с фильтрами where
Фильтры where в API позволяют использовать список фильтров или строку. Мы рекомендуем использовать список фильтров для производственных приложений, так как этот формат реализует все преимущества Predicate pushdown там, где это возможно.
Фильтры Where имеют несколько объектов, которые вы можете использовать:
-
Dimension()— Используется для любых категориальных или временных измерений.Dimension('metric_time').grain('week')илиDimension('customer__country'). -
TimeDimension()— Используется как более явное определение для временных измерений, опционально принимает гранулярностьTimeDimension('metric_time', 'month'). -
Entity()— Используется для сущностей, таких как первичные и внешние ключи -Entity('order_id').
Для TimeDimension() гранулярность требуется в фильтре WHERE только в том случае, если временные измерения агрегации для мер и метрик, связанных с фильтром where, имеют разные гранулярности.
Например, рассмотрим эту конфигурацию семантической модели и метрики, которая содержит две метрики, агрегированные по разным временным гранулярностям. Этот пример показывает одну семантическую модель, но то же самое относится к метрикам в более чем одной семантической модели.
semantic_model:
name: my_model_source
defaults:
agg_time_dimension: created_month
measures:
- name: measure_0
agg: sum
- name: measure_1
agg: sum
agg_time_dimension: order_year
dimensions:
- name: created_month
type: time
type_params:
time_granularity: month
- name: order_year
type: time
type_params:
time_granularity: year
metrics:
- name: metric_0
description: Метрика с месячной гранулярностью.
type: simple
type_params:
measure: measure_0
- name: metric_1
description: Метрика с годовой гранулярностью.
type: simple
type_params:
measure: measure_1
Предположим, пользователь запрашивает metric_0 и metric_1 вместе в одном запросе, допустимый фильтр WHERE будет:
"{{ TimeDimension('metric_time', 'year') }} > '2020-01-01'"
Недопустимые фильтры будут:
-
"{{ TimeDimension('metric_time') }} > '2020-01-01'"— метрики в запросе определены на основе мер с разными гранулярностями. -
"{{ TimeDimension('metric_time', 'month') }} > '2020-01-01'"—metric_1недоступна на месячной гранулярности.
- Используйте следующий пример для запроса с использованием фильтра
whereв строковом формате:
select * from {{
semantic_layer.query(metrics=['food_order_amount', 'order_gross_profit'],
group_by=[Dimension('metric_time').grain('month'),'customer__customer_type'],
where="{{ Dimension('metric_time').grain('month') }} >= '2017-03-09' AND {{ Dimension('customer__customer_type' }} in ('new') AND {{ Entity('order_id') }} = 10")
}}
- (Рекомендуется для лучшей производительности) Используйте следующий пример для запроса с использованием фильтра
whereв формате списка фильтров:
select * from {{
semantic_layer.query(metrics=['food_order_amount', 'order_gross_profit'],
group_by=[Dimension('metric_time').grain('month'),'customer__customer_type'],
where=["{{ Dimension('metric_time').grain('month') }} >= '2017-03-09'", "{{ Dimension('customer__customer_type') }} in ('new')", "{{ Entity('order_id') }} = 10"])
}}
Запрос с ограничением
Используйте следующий пример для запроса с использованием limit или order_by:
select * from {{
semantic_layer.query(metrics=['food_order_amount', 'order_gross_profit'],
group_by=[Dimension('metric_time')],
limit=10)
}}
Примеры запросов с order by
Order By может принимать простую строку, которая является Dimension, Metric или Entity, и по умолчанию будет использовать порядок по возрастанию
select * from {{
semantic_layer.query(metrics=['food_order_amount', 'order_gross_profit'],
group_by=[Dimension('metric_time')],
limit=10,
order_by=['order_gross_profit'])
}}
Для убывающего порядка вы можете добавить знак - перед объектом. Однако вы можете использовать эту сокращенную нотацию только в том случае, если вы не выполняете операции над объектом или используете полную нотацию объекта.
select * from {{
semantic_layer.query(metrics=['food_order_amount', 'order_gross_profit'],
group_by=[Dimension('metric_time')],
limit=10,
order_by=['-order_gross_profit'])
}}
Если вы упорядочиваете по объекту, который подвергся операции (например, вы изменили гранулярность временной размерности), или вы используете полную нотацию объекта, убывающий порядок должен выглядеть так:
select * from {{
semantic_layer.query(metrics=['food_order_amount', 'order_gross_profit'],
group_by=[Dimension('metric_time').grain('week')],
limit=10,
order_by=[Metric('order_gross_profit').descending(True), Dimension('metric_time').grain('week').descending(True) ])
}}
Аналогично, это приведет к порядку по возрастанию:
select * from {{
semantic_layer.query(metrics=['food_order_amount', 'order_gross_profit'],
group_by=[Dimension('metric_time').grain('week')],
limit=10,
order_by=[Metric('order_gross_profit'), Dimension('metric_time').grain('week')])
}}
Запрос с ключевым словом compile
-
Используйте следующий пример для запроса с использованием ключевого слова
compile:select * from {{
semantic_layer.query(metrics=['food_order_amount', 'order_gross_profit'],
group_by=[Dimension('metric_time').grain('month'),'customer__customer_type'],
compile=True)
}} -
Используйте следующий пример для компиляции SQL с сохраненным запросом. Вы можете использовать это для часто используемых запросов.
select * from {{ semantic_layer.query(saved_query="new_customer_orders", limit=5, compile=True}}
При запросе сохраненных запросов вы можете использовать такие параметры, как where, limit, order, compile и так далее. Однако имейте в виду, что вы не можете получить доступ к параметрам metric или group_by в этом контексте. Это связано с тем, что они являются предопределенными и фиксированными параметрами для сохраненных запросов, и вы не можете изменить их во время выполнения запроса. Если вы хотите запросить больше метрик или измерений, вы можете построить запрос, используя стандартный формат.
Запрос сохраненного запроса
Используйте следующий пример для запроса сохраненного запроса:
select * from {{ semantic_layer.query(saved_query="new_customer_orders", limit=5}}
JDBC API будет использовать сохраненный запрос (new_customer_orders) как определено и применит ограничение в 5 записей.
Алиасы метрик в запросах
Вы можете запрашивать метрики, используя алиасы. Алиасы позволяют использовать более простые или более интуитивно понятные имена для метрик вместо их полных определений.
select * from {{
semantic_layer.query(metrics=[Metric("revenue", alias="metric_alias")])
}}
Например, предположим, что в конфигурации метрик для метрики order_total задан алиас total_revenue_global. В этом случае вы можете запрашивать метрику, используя алиас вместо исходного имени:
select * from {{
semantic_layer.query(metrics=[Metric("order_total", alias="total_revenue_global")], group_by=['metric_time'])
}}
Результат будет следующим:
| METRIC_TIME | TOTAL_REVENUE_GLOBAL |
|:-------------:|:------------------: |
| 2023-12-01 | 1500.75 |
| 2023-12-02 | 1725.50 |
| 2023-12-03 | 1850.00 |
Обратите внимание, что при использовании Jinja-условий where необходимо указывать фактическое имя метрики. Например, если вы использовали banana в качестве алиаса для revenue, то в условии where нужно использовать реальное имя метрики — revenue, а не banana.
semantic_layer.query(metrics=[Metric("revenue", alias="banana")], where="{{ Metric('revenue') }} > 0")
Многошаговые (multi-hop) соединения
В случаях, когда вам нужно выполнить запрос через несколько связанных таблиц (многозвенные соединения), используйте аргумент entity_path, чтобы указать путь между связанными сущностями. Вот примеры того, как вы можете определить эти соединения:
- В этом примере вы запрашиваете измерение
location_name, но указываете, что оно должно быть соединено с использованием поляorder_id.{{Dimension('location__location_name', entity_path=['order_id'])}} - В этом примере измерение
salesforce_account_ownerсоединено с полемregion, с путем, проходящим черезsalesforce_account.{{ Dimension('salesforce_account_owner__region',['salesforce_account']) }}