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.