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

GraphQL StarterEnterpriseEnterprise +

GraphQL (GQL) — это open-source язык запросов для API. Он предлагает более эффективный и гибкий подход по сравнению с традиционными RESTful API.

С помощью GraphQL пользователи могут запрашивать конкретные данные с помощью одного запроса, что уменьшает необходимость в многочисленных обращениях к серверу. Это улучшает производительность и минимизирует сетевые издержки.

GraphQL имеет несколько преимуществ, таких как самодокументируемость, наличие системы строгой типизации, поддержка версионирования и эволюции, возможность быстрого развития и наличие мощной экосистемы. Эти функции делают GraphQL мощным выбором для API, которые придают приоритет гибкости, производительности и продуктивности разработчиков.

GraphQL API семантического слоя dbt

GraphQL API Semantic Layer позволяет исследовать и запрашивать метрики и измерения. Благодаря своей самодокументируемости вы можете удобно изучать доступные вызовы с помощью обозревателя схемы.

URL-адреса проводника схемы варьируются в зависимости от вашего региона развертывания. Используйте следующую таблицу, чтобы найти правильную ссылку для вашего региона:

Тип развертыванияURL проводника схемы
Северная Америка, мультиарендаторhttps://semantic-layer.cloud.getdbt.com/api/graphql
EMEA, мультиарендаторhttps://semantic-layer.emea.dbt.com/api/graphql
APAC, мультиарендаторhttps://semantic-layer.au.dbt.com/api/graphql
Одноарендаторhttps://semantic-layer.YOUR_ACCESS_URL/api/graphql

Замените YOUR_ACCESS_URL на ваш конкретный префикс аккаунта, за которым следует соответствующий URL доступа для вашего региона и плана.
Мультиячейкаhttps://YOUR_ACCOUNT_PREFIX.semantic-layer.REGION.dbt.com/api/graphql

Замените YOUR_ACCOUNT_PREFIX на ваш конкретный идентификатор аккаунта и REGION на ваше местоположение, например, us1.dbt.com.
Loading table...

Пример

  • Если ваш URL доступа для одноарендатора ABC123.getdbt.com, ваш URL проводника схемы будет https://semantic-layer.ABC123.getdbt.com/api/graphql.

Партнёры dbt могут использовать GraphQL API Semantic Layer для создания интеграций с Semantic Layer.

Обратите внимание, что GraphQL API Semantic Layer не поддерживает ref для обращения к объектам dbt. Вместо этого необходимо использовать полностью квалифицированное имя таблицы. Если вы используете макросы dbt во время выполнения запроса для расчёта метрик, эти вычисления следует перенести в определения метрик Semantic Layer в виде кода.

Требования для использования GraphQL API

Если вы пользователь dbt или партнер с доступом к dbt Cloud и семантическому слою dbt, вы можете настроить и протестировать этот API с данными из вашей собственной инстанции, настроив семантический слой и получив правильные параметры подключения GQL, описанные в этом документе.

Если вы пользователь или партнёр dbt и имеете доступ к dbt и Semantic Layer, вы можете настроить и протестировать этот API с данными из вашего собственного инстанса, сконфигурировав Semantic Layer и получив корректные параметры GQL‑подключения, описанные в этом документе.

Дополнительную информацию см. в руководстве Get started with the Semantic Layer.

Аутентификация выполняется с использованием либо dbt service account token, либо personal access token, передаваемого через HTTP‑заголовок следующим образом. Для изучения схемы вы можете указать эти данные в разделе header.

{"Authorization": "Bearer <AUTHENTICATION TOKEN>"}

Каждый GQL‑запрос также требует указания dbt environmentId. Для аутентификации API использует как service token или personal token, переданный в заголовке, так и значение environmentId.

Вызовы метаданных

Получение диалекта платформы данных

В некоторых случаях в вашем приложении может быть полезно знать диалект или платформу данных, которая используется внутри соединения Semantic Layer (например, если вы формируете фильтры where на основе пользовательского интерфейса, а не SQL, введённого пользователем).

GraphQL API имеет простой способ получить это с помощью следующего запроса:

{
environmentInfo(environmentId: BigInt!) {
dialect
}
}

Получение доступных метрик

metricsPaginated(
environmentId: BigInt!
search: String = null
groupBy: [GroupByInput!] = null
pageNum: Int! = 1
pageSize: Int = null
): MetricResultPage! {
items: [Metric!]!
pageNum: Int!
pageSize: Int
totalItems: Int!
totalPages: Int!
}

Получение доступных измерений для метрик

dimensionsPaginated(
environmentId: BigInt!
metrics: [MetricInput!]!
search: String = null
pageNum: Int! = 1
pageSize: Int = null
): DimensionResultPage! {
items: [Dimension!]!
pageNum: Int!
pageSize: Int
totalItems: Int!
totalPages: Int!
}

Получение доступных гранулярностей для заданных метрик

Примечание: Этот вызов для queryableGranularities возвращает только запрашиваемые гранулярности для времени метрики - основного временного измерения для всех выбранных метрик.

queryableGranularities(
environmentId: BigInt!
metrics: [MetricInput!]!
): [TimeGranularity!]!

Вы также можете получить запрашиваемые гранулярности для всех других измерений, используя вызов dimensions:

{
dimensionsPaginated(environmentId: BigInt!, metrics:[{name:"order_total"}]) {
items {
name
queryableGranularities # --> ["DAY", "WEEK", "MONTH", "QUARTER", "YEAR"]
}
}
}

Вы также можете опционально получить доступ к этому из конечной точки метрик:

{
metricsPaginated(environmentId: BigInt!) {
items {
name
dimensions {
name
queryableGranularities
}
}
}
}

Получение показателей

{
measures(environmentId: BigInt!, metrics: [{name:"order_total"}]) {
name
aggTimeDimension
}
}

aggTimeDimension сообщает вам имя измерения, которое соответствует metric_time для данной меры. Вы также можете запросить measures из конечной точки metrics, что позволяет вам увидеть, какие измерения соответствуют metric_time для данной метрики:

{
metricsPaginated(environmentId: BigInt!) {
items {
measures {
name
aggTimeDimension
}
}
}
}

Получение сущностей

entitiesPaginated(
environmentId: BigInt!
metrics: [MetricInput!] = null
search: String = null
pageNum: Int! = 1
pageSize: Int = null
): EntityResultPage! {
items: [Entity!]!
pageNum: Int!
pageSize: Int
totalItems: Int!
totalPages: Int!
}

Получение сущностей и измерений для группировки метрик

groupBysPaginated(
environmentId: BigInt!
metrics: [MetricInput!] = null
search: String = null
pageNum: Int! = 1
pageSize: Int = null
): EntityDimensionResultPage! {
items: [EntityDimension!]!
pageNum: Int!
pageSize: Int
totalItems: Int!
totalPages: Int!
}

Типы метрик

Metric {
name: String!
description: String
type: MetricType!
typeParams: MetricTypeParams!
filter: WhereFilter
dimensions: [Dimension!]!
queryableGranularities: [TimeGranularity!]!
}
MetricType = [SIMPLE, RATIO, CUMULATIVE, DERIVED]

Параметры типа метрики

MetricTypeParams {
measure: MetricInputMeasure
inputMeasures: [MetricInputMeasure!]!
numerator: MetricInput
denominator: MetricInput
expr: String
window: MetricTimeWindow
grainToDate: TimeGranularity
metrics: [MetricInput!]
}

Типы измерений

Dimension {
name: String!
description: String
type: DimensionType!
typeParams: DimensionTypeParams
isPartition: Boolean!
expr: String
queryableGranularities: [TimeGranularity!]!
}
DimensionType = [CATEGORICAL, TIME]

Список сохранённых запросов

Получить список всех сохранённых запросов для указанного окружения:

savedQueriesPaginated(
environmentId: BigInt!
search: String = null
pageNum: Int! = 1
pageSize: Int = null
): SavedQueryResultPage! {
items: [SavedQuery!]!
pageNum: Int!
pageSize: Int
totalItems: Int!
totalPages: Int!
}

Вывести сохранённый запрос

Вывести один сохранённый запрос, используя идентификатор окружения и имя запроса:


{
savedQuery(environmentId: "123", savedQueryName: "query_name") {
name
description
label
queryParams {
metrics {
name
}
groupBy {
name
grain
datePart
}
where {
whereSqlTemplate
}
}
}
}

Запросы

При выполнении запросов к данным необходимо указать либо groupBy, либо выборку metrics. В следующем разделе приведены примеры того, как выполнять запросы к метрикам:

Create query

createQuery(
environmentId: BigInt!
metrics: [MetricInput!]!
groupBy: [GroupByInput!] = null
limit: Int = null
where: [WhereInput!] = null
order: [OrderByInput!] = null
): CreateQueryResult
MetricInput {
name: String!
alias: String!
}

GroupByInput {
name: String!
grain: TimeGranularity = null
}

WhereInput {
sql: String!
}

OrderByinput { # -- передайте только один из metric или groupBy
metric: MetricInput = null
groupBy: GroupByInput = null
descending: Boolean! = false
}

Получение результата запроса

query(
environmentId: BigInt!
queryId: String!
): QueryResult!

GraphQL API использует процесс опроса для запросов, так как запросы могут быть долгими в некоторых случаях. Это работает путем создания запроса с мутацией createQuery, которая возвращает идентификатор запроса. Этот идентификатор затем используется для непрерывной проверки (опроса) результатов и статуса вашего запроса. Типичный поток будет выглядеть следующим образом:

  1. Запуск запроса
mutation {
createQuery(
environmentId: 123456
metrics: [{name: "order_total"}]
groupBy: [{name: "metric_time"}]
) {
queryId # => Возвращает 'QueryID_12345678'
}
}
  1. Опрос результатов
{
query(environmentId: 123456, queryId: "QueryID_12345678") {
sql
status
error
totalPages
jsonResult
arrowResult
}
}
  1. Продолжайте выполнять запрос 2. с соответствующим интервалом, пока статус не станет FAILED или SUCCESSFUL

Формат вывода и пагинация

Формат вывода

По умолчанию результат возвращается в формате Arrow. Вы можете переключиться на формат JSON с помощью соответствующего параметра. Однако из‑за ограничений производительности мы рекомендуем использовать параметр JSON только для тестирования и валидации.

Получаемый JSON представляет собой строку, закодированную в base64. Чтобы получить доступ к данным, вы можете декодировать её с помощью base64‑декодера. JSON формируется на основе pandas, что означает, что вы можете преобразовать его обратно в dataframe с помощью pandas.read_json(json, orient="table"). Либо вы можете работать с данными напрямую через json["data"], а схему таблицы получить из json["schema"]["fields"].

В качестве альтернативы вы можете передать encoded:false в поле jsonResult, чтобы сразу получить «сырой» JSON‑строку без кодирования.

По умолчанию вывод осуществляется в формате Arrow. Вы можете переключиться на формат JSON, используя следующий параметр. Однако из-за ограничений производительности мы рекомендуем использовать параметр JSON для тестирования и валидации. Полученный JSON является строкой, закодированной в base64. Чтобы получить к нему доступ, вы можете декодировать его с помощью декодера base64. JSON создается из pandas, что означает, что вы можете преобразовать его обратно в dataframe, используя pandas.read_json(json, orient="table"). Или вы можете работать с данными напрямую, используя json["data"], и найти схему таблицы, используя json["schema"]["fields"]. В качестве альтернативы, вы можете передать encoded:false в поле jsonResult, чтобы получить необработанную строку JSON напрямую.

{
query(environmentId: BigInt!, queryId: Int!, pageNum: Int! = 1) {
sql
status
error
totalPages
arrowResult
jsonResult(orient: PandasJsonOrient! = TABLE, encoded: Boolean! = true)
}
}

Результаты по умолчанию выводятся в таблицу, но вы можете изменить это на любое значение, поддерживаемое pandas.

Пагинация

По умолчанию мы возвращаем 1024 строки на страницу. Если ваш набор результатов превышает это значение, вам нужно увеличить номер страницы, используя опцию pageNum.

Запуск запроса на Python

arrowResult в ответе на GraphQL-запрос является дампом байтов, который не является визуально полезным. Вы можете преобразовать эти байтовые данные в таблицу Arrow, используя любой язык, поддерживающий Arrow. Обратитесь к следующему примеру на Python, объясняющему, как запросить и декодировать результат arrow:

import base64
import pyarrow as pa
import time

headers = {"Authorization":"Bearer <token>"}
query_result_request = """
{
query(environmentId: 70, queryId: "12345678") {
sql
status
error
arrowResult
}
}
"""

while True:
gql_response = requests.post(
"https://semantic-layer.cloud.getdbt.com/api/graphql",
json={"query": query_result_request},
headers=headers,
)
if gql_response.json()["data"]["status"] in ["FAILED", "SUCCESSFUL"]:
break
# Установите соответствующий интервал между запросами опроса
time.sleep(1)

"""
gql_response.json() =>
{
"data": {
"query": {
"sql": "SELECT\n ordered_at AS metric_time__day\n , SUM(order_total) AS order_total\nFROM semantic_layer.orders orders_src_1\nGROUP BY\n ordered_at",
"status": "SUCCESSFUL",
"error": null,
"arrowResult": "arrow-byte-data"
}
}
}
"""

def to_arrow_table(byte_string: str) -> pa.Table:
"""Получите необработанную строку base64 и преобразуйте в таблицу Arrow."""
with pa.ipc.open_stream(base64.b64decode(byte_string)) as reader:
return pa.Table.from_batches(reader, reader.schema)


arrow_table = to_arrow_table(gql_response.json()["data"]["query"]["arrowResult"])

# Выполните любую доступную функциональность, например, преобразование в таблицу pandas.
print(arrow_table.to_pandas())
"""
order_total ordered_at
3 2023-08-07
112 2023-08-08
12 2023-08-09
5123 2023-08-10
"""

Дополнительные примеры create-запросов

В этом разделе приведены примеры запросов для GraphQL API — например, как выполнять запросы метрик, измерений (dimensions), where-фильтров и других возможностей:

  • Query metric alias — Запрос с использованием псевдонима метрики, который позволяет использовать более простые или интуитивно понятные имена для метрик вместо их полных определений.
  • Query with a time grain — Получение нескольких метрик с изменением гранулярности временного измерения.
  • Query multiple metrics and multiple dimensions — Выбор общих измерений для нескольких метрик.
  • Query a categorical dimension on its own — Группировка по категориальному измерению.
  • Query with a where filter — Использование параметра where для фильтрации по измерениям и сущностям с помощью параметров.
  • Query with order — Запрос с использованием orderBy, принимает простую строку, соответствующую Dimension, Metric или Entity. По умолчанию используется сортировка по возрастанию.
  • Query with limit — Запрос с использованием условия limit.
  • Query saved queries — Запрос с использованием сохранённого запроса через параметр savedQuery для часто используемых запросов.
  • Query with just compiling SQL — Запрос, использующий ключевое слово compile через мутацию compileSql.
  • Query records — Просмотр всех запросов, выполненных в вашем проекте.

Псевдоним метрики запроса

mutation {
createQuery(
environmentId: "123"
metrics: [{name: "metric_name", alias: "metric_alias"}]
) {
...
}
}

Запрос с временной гранулярностью

mutation {
createQuery(
environmentId: "123"
metrics: [{name: "order_total"}]
groupBy: [{name: "metric_time", grain: MONTH}]
) {
queryId
}
}

Обратите внимание, что при использовании гранулярности в запросе вывод временного измерения с примененной к нему временной зернистостью всегда принимает форму имени измерения, дополненного двойным подчеркиванием и уровнем гранулярности - {time_dimension_name}__{DAY|WEEK|MONTH|QUARTER|YEAR}. Даже если гранулярность не указана, она также всегда будет иметь добавленную гранулярность и по умолчанию будет самой низкой доступной (обычно ежедневной для большинства источников данных). Рекомендуется указывать гранулярность при использовании временных измерений, чтобы не было неожиданных результатов с выходными данными.

Запрос нескольких метрик и нескольких измерений

mutation {
createQuery(
environmentId: "123"
metrics: [{name: "food_order_amount"}, {name: "order_gross_profit"}]
groupBy: [{name: "metric_time", grain: MONTH}, {name: "customer__customer_type"}]
) {
queryId
}
}

Запрос по категориальному измерению отдельно

mutation {
createQuery(
environmentId: "123"
groupBy: [{name: "customer__customer_type"}]
) {
queryId
}
}

Запрос с фильтром where

Фильтр where принимает аргумент списка (или строку для одного ввода). В зависимости от объекта, который вы фильтруете, есть несколько параметров:

  • Dimension() — Используется для любых категориальных или временных измерений. Например, Dimension('metric_time').grain('week') или Dimension('customer__country').

  • Entity() — Используется для сущностей, таких как первичные и внешние ключи, например, Entity('order_id').

Примечание: Если вы предпочитаете where-условие с более явным путем, вы можете опционально использовать TimeDimension() для разделения категориальных измерений от временных. Ввод TimeDimension принимает временное измерение и, опционально, уровень гранулярности. TimeDimension('metric_time', 'month').

mutation {
createQuery(
environmentId: "123"
metrics:[{name: "order_total"}]
groupBy:[{name: "customer__customer_type"}, {name: "metric_time", grain: month}]
where:[{sql: "{{ Dimension('customer__customer_type') }} = 'new'"}, {sql:"{{ Dimension('metric_time').grain('month') }} > '2022-10-01'"}]
) {
queryId
}
}

Для обоих TimeDimension() указание grain в фильтре where требуется только в том случае, если временные зерна агрегации у мер и метрик, связанных с этим фильтром where, различаются.

Example

Например, рассмотрим следующую конфигурацию семантической модели и метрик, которая содержит две метрики, агрегированные по разным временным зернам. В примере показана одна семантическая модель, но то же самое применимо и к метрикам, определённым в нескольких семантических моделях.

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: A metric with a month grain.
type: simple
type_params:
measure: measure_0
- name: metric_1
description: A metric with a year grain.
type: simple
type_params:
measure: measure_1

Предполагая, что пользователь запрашивает metric_0 и metric_1 вместе, ниже приведены примеры допустимых и недопустимых фильтров:

Пример
Фильтр

Допустимый фильтр
"{{ TimeDimension('metric_time', 'year') }} > '2020-01-01'"

Недопустимый фильтр
"{{ TimeDimension('metric_time') }} > '2020-01-01'"

Метрики в запросе определены на основе мер с разной гранулярностью.

Недопустимый фильтр
"{{ TimeDimension('metric_time', 'month') }} > '2020-01-01'"

metric_1 недоступна на уровне гранулярности «месяц».
Loading table...

Многошаговые соединения

В случаях, когда вам нужно выполнить запрос через несколько связанных таблиц (многопереходные соединения), используйте аргумент 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']) }}
#### Запрос с сортировкой \{#query-with-order}

```graphql
mutation {
createQuery(
environmentId: "123"
metrics: [{name: "order_total"}]
groupBy: [{name: "metric_time", grain: MONTH}]
orderBy: [{metric: {name: "order_total"}}, {groupBy: {name: "metric_time", grain: MONTH}, descending:true}]
) {
queryId
}
}

Запрос с ограничением (limit)

mutation {
createQuery(
environmentId: "123"
metrics: [{name:"food_order_amount"}, {name: "order_gross_profit"}]
groupBy: [{name:"metric_time", grain: MONTH}, {name: "customer__customer_type"}]
limit: 10
) {
queryId
}
}

Запрос сохранённых запросов

Этот вариант принимает те же входные параметры, что и мутация createQuery, но дополнительно включает поле savedQuery. Вы можете использовать его для часто используемых запросов.

mutation {
createQuery(
environmentId: "123"
savedQuery: "new_customer_orders"
) {
queryId
}
}
Примечание о выполнении сохранённых запросов

При выполнении сохранённых запросов вы можете использовать такие параметры, как where, limit, order, compile и другие. Однако имейте в виду, что в этом контексте нельзя обращаться к параметрам metric или group_by. Это связано с тем, что они являются предопределёнными и фиксированными параметрами для сохранённых запросов, и их нельзя изменить во время выполнения запроса. Если вам нужно запрашивать дополнительные метрики или измерения, вы можете построить запрос, используя стандартный формат.

Запрос только с компиляцией SQL

Этот вариант принимает те же входные параметры, что и мутация createQuery.

mutation {
compileSql(
environmentId: "123"
metrics: [{name:"food_order_amount"} {name:"order_gross_profit"}]
groupBy: [{name:"metric_time", grain: MONTH}, {name:"customer__customer_type"}]
) {
sql
}
}

История запросов

Используйте этот endpoint, чтобы просмотреть все запросы, выполненные в вашем проекте. Сюда входят как запросы Insights, так и запросы Semantic Layer.

{
queryRecords(
environmentId:123
) {
items {
queryId
status
startTime
endTime
connectionDetails
sqlDialect
connectionSchema
error
queryDetails {
... on SemanticLayerQueryDetails {
params {
type
metrics {
name
}
groupBy {
name
grain
}
limit
where {
sql
}
orderBy {
groupBy {
name
grain
}
metric {
name
}
descending
}
savedQuery
}
}
... on RawSqlQueryDetails {
queryStr
compiledSql
numCols
queryDescription
queryTitle
}
}
}
totalItems
pageNum
pageSize
}
}

Нашли ошибку?

0
Loading