Pular para o conteúdo

OData v4: subset, paginação 1.000, folding

Aula 3 de 69 minOperarAtualizada em 2026-10-04

Vídeo em produção

A gravação desta aula está no lote de produção. O objetivo, o exercício e a documentação já valem. Duração-alvo: 9 min.

Objetivo: Conectar Power BI/Excel ao `*_gold`

Selo de estado: Preview (teto atual do produto) · Curso ACD-250 — Integrações e consumo externo · Aula 3 de 6 · Atualizado em 2026-10-04.

Objetivo#

Ao final desta aula você vai conectar Power BI/Excel ao *_gold pelo feed OData v4 — sabendo o que o servidor dobra, o que ele recusa com 501 e por onde o custo entra.

Vídeo#

Identificador no manifesto: acd-250-03-odata-power-bi-excel · duração-alvo 9 min · tela do produto: /connect.

Roteiro de gravação (6 capítulos):

#Minutagem-alvoCapítuloTela do produto
10:00–0:45Abertura: título + selo. OData v4 é o formato que Power BI e Excel falam nativamente — sem conector custom./connect
20:45–2:30As três URLs: service document, $metadata e a entidade. O que cada uma responde./connect
32:30–4:30Power BI pelo caminho recomendado (M + Implementation = "2.0") e pelo caminho simples (Feed OData com ?api_key=)./connect
44:30–6:00Excel em três passos: a chave, a URL pronta, Dados → Obter Dados → Feed OData./excel
56:00–7:45Folding: o que vira $select/$filter/$orderby/$top/$count — e o 501 que recusa em voz alta em vez de filtrar errado./connect
67:45–9:00Paginação de 1.000, custo por bytes, atualização incremental em coluna de partição. Erros comuns e encerramento./excel

Conteúdo#

O ingestia.io expõe os marts publicados do seu datalake — os datasets *_gold e *_silver — como um feed OData v4. Isso importa por um motivo prático: Power BI, Excel e Tableau consomem OData v4 nativamente. Não há conector para instalar, nem gateway, nem driver. Você cola uma URL e as tabelas aparecem.

Três URLs, três respostas

URLO que respondeCusto
https://ingestia.io/api/v1/odataservice document: uma entidade por tabela publicadaR$ 0
https://ingestia.io/api/v1/odata/$metadataschema EDMX (XML) com os tipos das colunasR$ 0
https://ingestia.io/api/v1/odata/<tabela>página de linhas (até 1.000), com @odata.nextLinkbytes reais no BigQuery

Descobrir o que existe é grátis; ler linhas custa. Guarde essa divisão: ela explica quase todo o resto da aula.

Nas telas: /connect e /excel

/connect ("Conectar BI") traz a URL base e, por ferramenta, a receita pronta. No cartão Power BI, a URL do feed já vem montada no formato …/api/v1/odata?api_key=SUA_CHAVE, com o passo a passo: Obter Dados → Feed OData, colar, OK, selecionar as tabelas gold. O cartão do Tableau oferece o conector OData nativo com a mesma URL.

/excel ("Analisar no Excel") é o caminho mais curto e é área do dono. São três passos na tela: Passo 1, a chave (escolher uma existente ou criar); Passo 2, a URL pronta — com o aviso em destaque "Esta URL é um segredo"; Passo 3, o passo a passo dentro do Excel, incluindo o caminho Dados → Obter Dados → Consulta em Branco para quem quer o controle fino. A tela também lista as tabelas publicadas do workspace (só aurora_gold e aurora_silver), com camada, número de colunas e de linhas, para você escolher antes de abrir o Excel.

Power BI: o caminho recomendado

m
let
    Chave = "SUA_CHAVE",
    Fonte = OData.Feed("https://ingestia.io/api/v1/odata", null, [
        Headers = [ #"Authorization" = "Bearer " & Chave ],
        Implementation = "2.0"
    ]),
    Tabela = Fonte{[Name = "vendas"]}[Data]
in
    Tabela

Implementation = "2.0" não é opcional: é o que faz o Power Query falar OData v4 e, principalmente, dobrar (query folding) filtros e projeções para o servidor. Sem isso, o Power BI puxa a tabela inteira e filtra no seu computador — paga-se por tudo e espera-se por tudo. A vantagem extra desse caminho é que a chave vai no cabeçalho, não na URL.

Folding: o que roda no servidor

No Power QueryVira no servidor
Escolher/remover colunas$select
Filtrar com = <> > >= < <=$filter (eq/ne/gt/ge/lt/le)
Combinar com E / OU / NÃOand / or / not
Contém · Começa com · Termina comcontains / startswith / endswith
Manter as primeiras N linhas$top
Ordenar$orderby
Contagem$count=true

E aqui está a decisão de projeto mais importante do feed: um filtro que o servidor não sabe traduzir não é ignorado — ele responde 501, listando o que é suportado.

Nunca ignoramos um filtro em silêncio

Resultado errado é pior que erro. Fora do subset ficam $expand, $apply, $search, $compute, lambdas (any/all) e aritmética dentro do filtro; em texto, só contains/startswith/endswith. $format: apenas JSON. Recebeu 501? Simplifique o filtro, ou aplique-o localmente depois da carga.

Paginação e custo

O feed pagina server-driven: páginas de até 1.000 linhas, com @odata.nextLink na resposta. Power BI e Excel seguem esse link automaticamente até o fim — e você deve seguir o link exatamente como recebido, porque ele carrega um $skiptoken opaco; token adulterado responde 400. Precisa de página menor? Prefer: odata.maxpagesize=N (teto 1.000), e a resposta confirma com Preference-Applied. A profundidade máxima é 1.000.000 de linhas por consulta: acima disso vem 400 pedindo que você filtre — porque cada página varre a tabela no BigQuery.

Isso leva à regra de dinheiro deste canal: paginar tabela grande sem filtro é a forma mais cara de extrair dados. $select e $filter reduzem bytes de verdade (são pushdown); paginar não. $count=true roda um COUNT(*) adicional, também contado. Cada chamada deixa rastro na auditoria como api.odata.read, com bytes, página e chave — separável do BI nativo. E o x-ingestia-cost-brl que volta no cabeçalho é projeção, não preço faturado.

A receita boa: atualização incremental. Crie os parâmetros RangeStart/RangeEnd (Data/Hora), filtre com each [data] >= RangeStart and [data] < RangeEnd e configure a política. O filtro por data dobra para o servidor e, se a coluna for de partição, o BigQuery poda partições e o byte lido cai de verdade.

Exemplo: a Aurora Varejo no Power BI

Maria conecta o relatório da diretoria em aurora_gold.vendas. No Editor Avançado, ela usa o OData.Feed com cabeçalho, escolhe só data, filial e total (vira $select), filtra data >= 2026-01-01 (vira $filter) e configura atualização incremental de 25 meses sobre data, que é a coluna de partição do mart. O refresh diário passa a ler uma janela, não a tabela. Quando um analista tenta adicionar um passo com ANO(data) = 2026, o feed responde 501 — aritmética e funções de data em filtro estão fora do subset; a correção é filtrar por intervalo de datas, que dobra.

SuperfícieEstadoQuando usar
Feed OData v4 + kit Power BI/ExcelPreviewé o caminho de consumo externo hoje — este é o uso certo
API REST /api/v1/tables (listar/paginar)Fora de GAnão construa sobre ela; o mesmo dado sai pelo OData (Aula 6)
Atualização por evento (webhook)Roadmapnão existe — use atualização incremental programada

Erros comuns

SintomaCausa provávelO que fazer
501 ao adicionar um passo de filtrooperação fora do subset ODatasimplifique o $filter ou filtre depois da carga
400 $skiptoken inválidoo link de paginação foi alterado à mãosiga o @odata.nextLink exatamente
400 na paginação profundapassou de 1.000.000 de linhasfiltre antes; não pagine a tabela inteira
429estourou 120 req/min por chave (240/min por workspace)respeite o Retry-After; reduza paralelismo (Aula 5)
503 no feeddatalake não provisionado, ou nuvem própria caídatente de novo; confirme o provisionamento — o feed nunca devolve coleção vazia
Coluna faltando no Power BIé PII, ou é STRUCT/RECORDPII nunca sai pela API; publique colunas planas
Custo alto no fim do mêspaginação de tabela grande sem filtroatualização incremental em coluna de partição
Refresh lento e caro mesmo com filtrofaltou Implementation = "2.0" — não dobroucorrija o M; confira com Exibir consulta nativa

Estado

OData v4 e o kit Power BI/Excel são Preview — funcionam, são documentados e cobertos por teste (o pushdown é testado), sem SLA. O que mantém o selo aqui: a validação do folding real fim a fim com Power BI e Excel é gate humano, acompanhada continuamente, e o claim de /api/v1 como GA está barrado por evidência pendente. Sem datalake provisionado (demo), o feed serve dados claramente simulados e $filter/$orderby/$count respondem 503 — ele nunca finge que filtrou.

Faça você mesmo#

No workspace de treino Aurora Varejo, como dona (comece em /connect, depois /excel):

  1. Em /connect, copie a URL base da API e confirme o nome do dataset gold (aurora_gold). Tenha em mãos uma chave válida da Aula 2.
  2. Chame o service document com o cabeçalho: curl -H "Authorization: Bearer <sua chave>" https://ingestia.io/api/v1/odata. Confirme 200 e localize a entidade vendas na lista.
  3. Chame $metadata e localize o tipo EDM da coluna data. Confirme que nenhuma coluna de PII aparece no documento.
  4. Puxe uma página com projeção, filtro, ordenação e contagem: $select=data,total, $filter=data ge 2026-01-01, $orderby=data, $count=true. Localize na resposta o @odata.count e o @odata.nextLink.
  5. Provoque o 501 de propósito: acrescente um filtro fora do subset (por exemplo, um $filter com aritmética). Leia a mensagem e confirme que ela lista o que é suportado.
  6. Em /excel, escolha a chave no Passo 1, copie a URL pronta do Passo 2 e siga o Passo 3 até ver as tabelas de aurora_gold listadas no Excel. Leia o aviso de que a URL é um segredo.
  7. No Power BI Desktop, monte a consulta em M com Implementation = "2.0" e cabeçalho Authorization, aponte para vendas e configure RangeStart/RangeEnd sobre a coluna data.
  8. Compare, no cabeçalho x-ingestia-cost-brl de duas chamadas, uma leitura com $select + $filter e outra sem — e escreva uma frase explicando por que paginar não reduz bytes.

Você terminou quando tiver o feed carregando no Excel e no Power BI a partir de aurora_gold, tiver visto um 501 de filtro fora do subset com os próprios olhos, e conseguir explicar em uma frase o que o folding economiza.

Checagem rápida#

Três perguntas no final da aula, corrigidas no servidor. A aula só conta como concluída depois da checagem.

Documentação relacionada#

Capacidades ensinadas#

C10.6 — o selo exibido na aula é sempre o estado mais conservador entre as capacidades citadas; nada aqui é "GA".

Carregando seu progresso…