Pular para o conteúdo principal

Normalize a estrutura antes da qualidade e escreva.

Os conectores recuperam dados. As transformações tornam o DataFrame físico utilizável antes da execução das regras de qualidade e dos modos de gravação. Use este namespace para mutações que alteram linhas, colunas ou valores. Mantenha descrições de catálogo, PII, aliases e propriedade empresarial em contratos de governança divididos.

O namespace canônico

Use transform para preparação física do DataFrame. O atalho de nível superior shape permanece compatível com notebooks simples, mas novos contratos devem usar o namespace canônico.

A ordem de execução é determinística:

  1. select_columns
  2. column_mapping
  3. transform.shape
  4. transform.cast
  5. transform.standardize
  6. transform.derive
  7. filter_expression
  8. custom_keys
  9. watermark_columns
  10. transform.deduplicate
  11. codificação de colunas de limpeza e controle
transform:
shape:
parse_json:
- column: raw_response
alias: payload
schema: "STRUCT<events:ARRAY<STRUCT<id:STRING,title:STRING>>>"
arrays:
- path: payload.events
mode: explode_outer
alias: event
columns:
event.id:
alias: event_id
cast: STRING
event.title:
alias: event_title
cast: STRING
cast:
event_id: string
standardize:
event_title:
trim: true
normalize_whitespace: true
derive:
event_date: to_date(ingestion_ts_utc)
deduplicate:
keys: [event_id]
order_by:
- column: ingestion_ts_utc
direction: desc
nulls: last

Princípios de design

Esquema explícito

A análise de JSON requer Spark DDL. Evite confiar na inferência de runtime para contratos importantes.

Cardinalidade é intencional

As operações de explosão alteram as contagens de linhas. Bronze bloqueia alterações inseguras de cardinalidade, a menos que seja explicitamente permitido.

Colunas são projeções

Quando columns é declarado, apenas os aliases declarados permanecem como colunas de negócios.

Conectores permanecem neutros

A estruturação de negócios pertence às transformações, não às soluções alternativas específicas do conector.

Os metadados ficam fora da transformação

Se um campo descreve significado, propriedade, PII, classificação ou capacidade de descoberta do catálogo, ele pertence a annotations ou operations, não a transform.

Onde o esquema pertence

ContractForge usa declarações de esquema em dois locais diferentes. Eles não devem ser tratados como campos intercambiáveis.

LocalizaçãoPropósitoUse-o paraNão use para
source.read.schemaEsquema de linha de origem física usado enquanto um conector ou leitor Spark materializa dados.CSV, JSON, XML, Avro, pastas de arquivos e REST response.mode: records onde a inferência seria frágil.Business JSON dentro de uma coluna de string já lida.
schemas de nível superior com shape.parse_json.schema_refSpark DDL reutilizável para analisar uma string JSON depois que um DataFrame já existir.Corpo do Event Hubs, resposta bruta REST, colunas de carga útil de texto e formatos de envelope.Configurando como o Spark lê os arquivos de origem originais ou registros do conector.
annotationsMetadados de catálogo e governança.Descrições, aliases, tags, PII, confidencialidade e contexto de produto de dados.Qualquer comportamento de transformação, lançamento, explosão ou análise.

Regra prática

Se o Spark precisar do esquema para ler a fonte, coloque-o em source.read.schema. Se ContractForge já tiver uma coluna de string e precisar analisar seu conteúdo JSON, coloque o DDL em schemas de nível superior e referencie-o em transform.shape.parse_json.

Referência de campo de transformação

CampoTipoObrigatórioComportamento
shapeobjetoNãoAnalisa strings JSON, nivela estruturas, manipula matrizes e projeta colunas aninhadas.
caststring do mapa -> stringNãoConverte colunas existentes em tipos Spark SQL, como string, double, timestamp ou decimal(18,2).
standardizestring do mapa -> objetoNãoAplica limpeza de cadeia determinística às colunas declaradas.
standardize.<column>.trimbooleanoNãoApara espaços em branco à esquerda e à direita.
standardize.<column>.lowerbooleanoNãoConverte o texto em minúsculas. Não pode ser combinado com upper.
standardize.<column>.upperbooleanoNãoConverte texto em maiúsculas. Não pode ser combinado com lower.
standardize.<column>.normalize_whitespacebooleanoNãoSubstitui espaços em branco repetidos por um único espaço.
standardize.<column>.empty_as_nullbooleanoNãoConverte a string vazia final em nula.
derivestring do mapa -> stringNãoCria ou substitui colunas usando expressões Spark SQL.
deduplicate.keysstring ou listaSim, quando deduplicate existeColunas-chave usadas para manter uma linha por chave.
deduplicate.order_bystring ou listaSim, quando deduplicate existeOrdenação determinística. Prefira o formulário de lista estruturada para novos contratos.
deduplicate.order_by[].columnstringSim para itens de pedidos estruturadosColuna usada para ordenação.
deduplicate.order_by[].directionasc ou descNãoOrdenar direção. O padrão é desc.
deduplicate.order_by[].nullsfirst ou lastNãoCláusula de ordenação nula.

Elenco, padronização e derivação

Use essas operações quando a origem já for tabular o suficiente e o contrato de destino precisar de preparação explícita de valor sem código de notebook personalizado.

transform:
cast:
order_id: string
amount: decimal(18,2)
updated_at: timestamp
standardize:
customer_email:
trim: true
lower: true
empty_as_null: true
status:
trim: true
upper: true
normalize_whitespace: true
derive:
order_date: to_date(updated_at)
net_amount: amount - coalesce(discount_amount, 0)

Use cast para preparação do tipo de destino, standardize para limpeza simples de string e derive para expressões Spark SQL que criam colunas. Se a expressão se tornar uma grande lógica de negócios, promova-a para uma visão revisada, etapa de notebook ou modelo downstream.

Referência de campo de forma

O contrato shape é executado após o conector de origem e antes das regras de qualidade e modos de gravação. Destina-se à normalização física de registros aninhados ou semiestruturados, não à agregação de negócios.

CampoTipoObrigatórioComportamento
parse_jsonlistaNãoAnalisa colunas de string declaradas com um esquema Spark DDL explícito usando from_json.
parse_json[].columnstringSimColuna de cadeia de caracteres de origem ou caminho de cadeia de caracteres aninhada a ser analisado.
parse_json[].schemastringSimEsquema DDL do Spark. Use STRUCT<...>, ARRAY<...> ou qualquer tipo de dados Spark válido aceito por from_json.
parse_json[].aliasstringNãoColuna de saída. Obrigatório ao analisar um caminho aninhado. Deve ser um nome simples de coluna de nível superior.
parse_json[].drop_sourcebooleanoNãoDescarta a coluna de origem original após a análise. Compatível apenas com colunas de origem de nível superior.
flatten.enabledbooleanoNãoAchata campos struct em colunas de nível superior.
flatten.separatorstringNãoSeparador usado em nomes de colunas geradas. O comportamento padrão segue o padrão de implementação.
flatten.max_depthinteiroNãoProfundidade máxima de aninhamento de estrutura para nivelar.
flatten.includelistaNãoColunas estruturais de nível superior para nivelar. Outras colunas são mantidas como estão.
flatten.excludelistaNãoCaminhos a serem excluídos do nivelamento.
zip_arrayslistaNãoCombina matrizes paralelas em uma matriz de estruturas antes de explodir.
zip_arrays[].aliasstringSimColuna da matriz de saída contendo estruturas.
zip_arrays[].columnsmapaSimMapa do caminho da matriz de origem para o nome do campo struct de saída. Requer pelo menos duas matrizes.
arrayslistaNãoTransforma arrays mantendo, serializando, dimensionando, pegando o primeiro elemento ou explodindo.
arrays[].pathstringSimCaminho da matriz. Use notação de ponto; não use a sintaxe [].
arrays[].modeenumeraçãoNãokeep, to_json, size, first, explode ou explode_outer.
arrays[].aliasstringNãoColuna de saída. Obrigatório implicitamente para modos de alteração de cardinalidade quando nenhum alias padrão é desejado.
arrays[].allow_cartesianbooleanoNãoPermite múltiplas explosões de irmãos que podem multiplicar linhas. O padrão protege contra expansão cartesiana acidental.
columnsmapaNãoProjeção final. Quando declarado, apenas as colunas projetadas são mantidas.
columns.<path>.aliasstringNãoColuna de saída. O padrão é o caminho com pontos substituídos por sublinhados quando nenhuma expressão é usada.
columns.<path>.caststringNãoTipo Spark SQL usado para converter a expressão projetada.
columns.<path>.expressionstringNãoExpressão SQL do Spark. Requer um alias explícito.
allow_cardinality_change_on_bronzebooleanoNãoPermite explode/explode_outer em contratos bronze quando o contrato altera intencionalmente a cardinalidade da linha.

Matrizes paralelas

Use zip_arrays antes de explodir quando uma API retornar vários arrays que representam observações alinhadas.

transform:
shape:
zip_arrays:
- alias: hourly_observation
columns:
payload.hourly.time: time
payload.hourly.temperature_2m: temperature
payload.hourly.relative_humidity_2m: humidity
arrays:
- path: hourly_observation
mode: explode_outer
alias: observation

Padrões de exemplo

NASA EONETE

JSON REST bruto para linhas

O conector REST captura JSON bruto, parse_json aplica um esquema DDL explícito e a explosão de matriz transforma eventos em registros prateados.

Open-Meteo

Matrizes paralelas

As respostas meteorológicas por hora retornam matrizes alinhadas. zip_arrays preserva o significado posicional antes de explodir.

Terremotos USGS

Estruturas e coordenadas aninhadas

Campos estruturais e índices de array podem ser projetados de forma declarativa, mantendo os notebooks livres do encanamento de colunas do Spark.

Arquivos blob/S3

Esquema primeiro

Esquemas de arquivos explícitos mais transform.deduplicate tornam os exemplos de armazenamento de objetos determinísticos e revisáveis.

Desduplicação determinística

Use transform.deduplicate quando um lote puder conter vários registros para a mesma chave comercial e o contrato tiver uma regra de pedido clara.

transform:
deduplicate:
keys: [order_id]
order_by:
- column: updated_at
direction: desc
nulls: last
- column: sequence
direction: desc

Para contratos existentes, fragmentos SQL como updated_at DESC NULLS LAST ainda são aceitos. Para novos contratos, prefira a lista estruturada porque é mais fácil de validar e revisar.

Mapeamento de coluna versus forma

Use column_mapping para renomeações simples de origem para destino antes de colunas técnicas serem adicionadas. Use transform.shape.columns quando a projeção de destino precisar de conversões, caminhos aninhados, expressões, índices de array ou uma reescrita estrutural completa.

column_mapping:
id: customer_id
ingestion_date: source_ingestion_date

transform:
shape:
columns:
properties.mag:
alias: magnitude
cast: DOUBLE
geometry.coordinates[0]:
alias: longitude
cast: DOUBLE

Matrizes aninhadas em qualquer ordem

Para matrizes aninhadas, declare o pai explodido e, em seguida, faça referência ao alias gerado nas operações filho. ContractForge resolve caminhos de array pendentes iterativamente, para que o contrato possa expressar a hierarquia pretendida sem código Spark personalizado.

transform:
shape:
arrays:
- path: payload.orders
mode: explode_outer
alias: order
- path: order.items
mode: explode_outer
alias: item
columns:
order.id:
alias: order_id
cast: STRING
item.sku:
alias: sku
cast: STRING
item.quantity:
alias: quantity
cast: INT

Regra de cardinalidade

Duas explosões de irmãos sob o mesmo pai são bloqueadas, a menos que allow_cartesian seja verdadeiro. As explosões pai-filho são válidas porque cada etapa tem um caminho de expansão de linha claro.

Guarda-corpos

  • A análise JSON requer um esquema Spark DDL declarado; isso evita desvios acidentais de inferência.
  • A alteração da cardinalidade no Bronze é bloqueada por padrão porque as camadas brutas normalmente devem preservar os registros de origem.
  • Matrizes irmãs não são explodidas independentemente, a menos que o contrato evite produtos cartesianos acidentais.
  • A ordem de desduplicação deve ser determinística para os modos de mesclagem e diferença de hash.
  • lower e upper não podem ser habilitados juntos para a mesma coluna padronizada.
  • cast, standardize e deduplicate.keys exigem que existam colunas depois de shape e antes da gravação.