Creazione del modulo del prodotto di dati

La creazione di un modulo prodotto di dati personalizzato è necessaria per definire la tua logica di business e i tuoi modelli analitici, consentendoti di eseguire calcoli sulle tabelle di base e di raggrupparli in set di dati implementabili.

Prerequisiti

Quando crei un modulo di prodotto dati personalizzato, ti consigliamo vivamente di utilizzare uno spazio dei nomi personalizzato dedicato per il packaging. Inoltre, assicurati che la tabella di origine che prevedi di utilizzare esista nel set di dati della base dati.

Creazione di un modulo del prodotto di dati

La definizione del modulo del prodotto di dati richiede i seguenti passaggi:

  • Registrazione del modulo del prodotto di dati all'interno del file config/config.yaml, estendendo l'elenco data.modules.products con la voce:
[...]
data:
  [...]
  # Configuration for data foundation and product modules.
  modules:
    # List of foundation modules.
    foundation:
      [...]
    # List of data product modules.
    product:
      [...]
      - moduleId:  product_module_id
        type:  custom_namespace.flight_usd
        dependsOn:
          sapModule: erp
          sapModuleCustNS:  foundation_module_id
        dataTargetId: product_target
        enabled: true
        tableSettings: "table_settings.yaml"
        # Optional, references file in `config/custom_namespace_path/data_product/product_module_id/`
        # If omitted, defaults to src/data_modules/custom_namespace_path/data_product/table_settings.default.yaml.
[...]
  • Creazione del file tableSettings (ad es. config/custom_namespace_path/data_product/product_module_id/table_settings.yaml). Questo file YAML controlla le configurazioni delle tabelle, come le materializzazioni e i dettagli di ottimizzazione di BigQuery:
common:
  custom_sales_summary:
    materialization_type: "table"
    tags: ["custom", "sales", "reporting"]
    partition_details:
      column: "created_date"
      partition_type: "date"
      time_grain: "day"
    cluster_details:
      columns:
        - "customer_id"
  • Creazione del file di annotazioni

Il file di annotazione <tablename>.yaml viene creato per ogni artefatto di output del prodotto di dati (tabella, visualizzazione) e descrive colonne e campi in formato YAML. Durante la compilazione, il builder cerca automaticamente le annotazioni all'interno della cartella annotations/ del prodotto (ad es. annotations/custom_sales_summary.yaml), unisce queste stringhe direttamente nelle definizioni dello schema Dataform di output in modo che vengano conservate nei metadati della tabella BigQuery.

Un file config/custom_namespace_path/data_product/product_module_id/annotations/'tablename'.yaml di annotazioni ha il formato:

description: "Description of the table or view purpose"
fields:
  - name: "customer_id"                     # column name
    description: "Customer identifier"      # column description
  - name: "column2"
    description: "Description of Column 2"
  - name: "column3"
    description: "Description of Column 3"
  • Crea un file manifest.yaml nella cartella del prodotto di dati config/custom_namespace_path/data_product/product_module_id/, mantenendo le dipendenze di tipo, tabelle e moduli. Il file manifest segue questo formato:

type: sales_performance
builder: sap_product     # Automatically resolves to the global SapProductBuilder fallback
dependencies:
  sapModule:
    type: sap
    supportedVersions:
      - ecc
      - s4

Esempio di modulo del prodotto di dati

Per l'esempio di voli che stiamo creando src/data_modules/custom_namespace_path/data_product/product_module_id/manifest.yaml con i contenuti

type: product_module_id
dependencies:
  sapModule:
    type: cortex.sap
    supported_versions:
      - ecc
      - s4
    tables:
      common:
        - tcurr
  sapModuleCustNS:
    type:  custom_namespace .sap
    supported_versions:
      - ecc
      - s4
    tables:
      common:
        - sflight
builder: sap_product
  • Nel passaggio successivo, estendi il file delle impostazioni della tabella a cui viene fatto riferimento per le tabelle dei prodotti di dati.

Nell'esempio utilizzato, crea config/custom_namespace_path/data_product/product_module_id/table_settings.yaml con il seguente contenuto:

ecc:
  flights_usd:
    materializationType: incremental
    tags: [sap, dataproduct, masterdata]
s4:
  flights_usd:
    materializationType: incremental
    tags: [sap, dataproduct, masterdata]

  • Crea annotazioni per le tabelle dei prodotti di dati per arricchire lo schema di archiviazione con descrizioni.

Nell'esempio utilizzato, crea il file src/data_modules/custom_namespace_path/data_product/product_module_id/annotations/flights_usd.yaml con il seguente contenuto:

description: "Flight scheduling and pricing information, including currency conversion to USD."
fields:
  - name: "client_mandt"
    description: "Client (Mandant), PK"
  - name: "airline_code_carrid"
    description: "Airline Carrier ID, PK"
  - name: "flight_connection_number_connid"
    description: "Flight Number, PK"
  - name: "flight_date_fldate"
    description: "Flight Date"
  - name: "price_usd"
    description: "Price in USD"
  - name: "price"
    description: "Price in local currency"
  - name: "currency"
    description: "Local currency"
  • La logica di business del prodotto di dati è archiviata nei file js o sqlx.

Nell'esempio riportato, crea il file src/data_modules/custom_namespace_path/data_product/product_module_id/definitions/flights_usd.js con il seguente contenuto:

// ___MODULE_CONTEXT___
// ___TABLE_CONFIG___

const moduleConfig = config.product[moduleContext.moduleId];
const sapModuleConfigDatasetId = moduleConfig.sources.sapModule.datasetId;
const sapModuleCustNSConfigDatasetId = moduleConfig.sources.sapModuleCustNS.datasetId;

const materializationType = tableConfig.materializationType || "incremental";

const incremental = require("includes/cortex/incremental.js");
const publish_config = require("includes/cortex/publish_config.js");

const publishConfig = publish_config.getPublishConfig(
   materializationType,
   tableConfig,
   moduleConfig,
   [
       "client_mandt",
       "airline_code_carrid",
       "flight_connection_number_connid",
       "flight_date_fldate"
   ]
);

publish("flight_usd", publishConfig).query(
   (ctx) => `
WITH flight_base AS (
   SELECT
       mandt,
       carrid,
       connid,
       fldate,
       price,
       currency,
       -- Convert flight date string (YYYYMMDD) to an integer to calculate SAP's inverted date key
       CAST(99999999 - CAST(fldate AS INT64) AS STRING) AS inverted_fldate
   FROM   ${ctx.ref(sapModuleCustNSConfigDatasetId, 'sflight')} AS flight
),
ranked_exchange_rates AS (
   SELECT
       f.mandt,
       f.carrid,
       f.connid,
       f.fldate,
       f.price,
       f.currency,
       t.ukurs,
       -- Window function to grab the closest historical exchange rate
       ROW_NUMBER() OVER (
           PARTITION BY f.mandt, f.carrid, f.connid, f.fldate
           ORDER BY t.gdatu ASC
       ) AS latest_rate_rank
   FROM flight_base f
   LEFT JOIN ${ctx.ref(sapModuleConfigDatasetId, 'tcurr')} AS t
     ON f.mandt = t.mandt
    AND t.kurst = 'M'       -- 'M' is the standard SAP default for average exchange rates
    AND t.fcurr = f.currency
    AND t.tcurr = 'USD'
    -- Chronological (rate_date <= flight_date) translates to (t.gdatu >= inverted_fldate)
    AND t.gdatu >= f.inverted_fldate
)

SELECT
   client_mandt,
   airline_code_carrid,
   flight_connection_number_connid,
   flight_date_fldate,
   price,
   currency,
   price_usd,
   CURRENT_TIMESTAMP() AS bq_loaded_at
FROM (
  SELECT
    mandt              AS client_mandt,
    carrid             AS airline_code_carrid,
    connid             AS flight_connection_number_connid,
    PARSE_TIMESTAMP('%Y%m%d', fldate) AS flight_date_fldate,
    price              AS price,
    currency           AS currency,
    -- Currency Conversion Logic
    CASE
       WHEN currency = 'USD' THEN price
       WHEN ukurs IS NULL   THEN NULL -- Handles cases where no exchange rate is found
       -- If UKURS is negative, it's an indirect quotation (1 USD = X Local) -> Divide
       WHEN ukurs < 0       THEN ROUND(price / ABS(ukurs), 2)
       -- If UKURS is positive, it's a direct quotation (1 Local = X USD) -> Multiply
       ELSE ROUND(price * ukurs, 2)
     END AS price_usd
  FROM ranked_exchange_rates
  WHERE latest_rate_rank = 1
)
${incremental.getWhere(ctx, ["flight_date_fldate"])}
`
);

Verifica dell'estensione dello spazio dei nomi personalizzato

Per verificare l'estensione riuscita di Google Cloud Cortex Framework con spazi dei nomi, moduli di base dei dati o di prodotto per dati, segui questi passaggi:

  1. Per eseguire il deployment del modulo del prodotto di dati, esegui uv run targets build, deploy o build-and-deploy, come descritto nella pagina Deployment.

  2. Apri la UI di Dataform nella console BigQuery e vai al repository e allo spazio di lavoro.

  3. Nell'interfaccia utente di Dataform, assicurati che nella console non vengano visualizzati errori di compilazione.

  4. Verifica che le estensioni preparate siano state implementate nei percorsi definitions/data_foundation/custom_namespace_path/ e definitions/data_product/product_module_id/.

  5. Segui le istruzioni per l'esecuzione delle pipeline Dataform.

  6. Verifica in BigQuery che il set di dati del prodotto contenga la tabella del prodotto di dati e che sia compilato con i dati.