Creación de módulos de productos de datos

Para definir tu propia lógica empresarial y modelos analíticos, crea un módulo de productos de datos personalizado. Esto te permite ejecutar cálculos en tus tablas de base o productos de datos ascendentes y empaquetar los resultados en conjuntos de datos implementables.

Requisitos previos

Te recomendamos crear módulos de productos de datos personalizados en un espacio de nombres personalizado dedicado para mejorar la administración del ciclo de vida. Además, asegúrate de que la tabla de origen que planeas usar exista en el conjunto de datos de la base de datos.

Creación de un módulo de productos de datos

La definición del módulo de productos de datos requiere los siguientes pasos:

  • Registro del módulo de productos de datos en el archivo config/config.yaml. Para ello, extiende la lista data.modules.products con la entrada:
data:
  # Configuration for data foundation and product modules.
  modules:
    # List of data product modules.
    product:
        # Recommended naming for product_module_id:
        # custom_namespace_data_product_module_type
      - moduleId:  product_module_id
        # Type of the data product (namespaced).
        type:  custom_namespace.data_product_module_type
        # Map of module dependencies.
        dependsOn:
          sapModule: erp
          sapModuleCustNS:  foundation_module_id
        # Reference to the target dataset ID.
        dataTargetId: product_target
        # Whether the module is enabled.
        # enabled: true
        # Whether the foundation is external (does not create target dataset).
        # external: false
        # Custom table settings file, relative to 'config/' file directory
        # Recommended path: '{custom_namespace}/data_product/{data_product_module_type}/table_settings.yaml'
        # If omitted, defaults to '../src/data_modules/{custom_namespace}/data_product/{data_product_module_type}/table_settings.default.yaml'
        # tableSettings: "{custom_namespace}/data_product/{data_product_module_type}/table_settings.yaml"
        
  • Creación del archivo tableSettings predeterminado (p.ej., src/data_modules/custom_namespace/data_product/data_product_module_type/table_settings.default.yaml).

Este archivo YAML controla las configuraciones de la tabla, como las materializaciones y los detalles de optimización de 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"
  • Creación del archivo de anotaciones

El archivo de anotaciones tablename.yaml se crea para cada artefacto de salida del producto de datos (tabla, vista) y describe las columnas y los campos en formato YAML. Durante la compilación, el compilador busca automáticamente anotaciones en la carpeta annotations/ del producto (p.ej., src/data_modules/custom_namespace/data_product/data_product_module_type/annotations/custom_sales_summary.yaml), une estas cadenas directamente en las definiciones del esquema de Dataform de salida para que se conserven en los metadatos de la tabla de BigQuery.

Un archivo de anotaciones src/data_modules/custom_namespace/data_product/data_product_module_type/annotations/tablename.yaml tiene el siguiente 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 archivo manifest.yaml en tu carpeta de productos de datos src/data_modules/custom_namespace/data_product/data_product_module_type/, manteniendo el tipo, las tablas y las dependencias del módulo. El archivo de manifiesto tiene el siguiente formato:

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

Ejemplo de módulo de productos de datos

Los pasos para implementar el producto de datos flights_usd en el espacio de nombres: sap_bookingdatamodel del ejemplo de vuelos son los siguientes:

  • Registro del módulo de productos de datos en el archivo config/config.yaml. Para ello, extiende la lista data.modules.products con la entrada:
data:
  modules:
    product:
      - moduleId: sap_bookingdatamodel_flights_usd
        type: sap_bookingdatamodel.flights_usd
        dependsOn:
          sapModule: erp
          sapModuleCustNS: sap_bookingdatamodel
        dataTargetId: product_target
  • A continuación, crea src/data_modules/custom_namespace/data_product/data_product_module_type/manifest.yaml con el contenido
type: flights_usd
dependencies:
  sapModule:
    type: cortex.sap
    supported_versions:
      - ecc
      - s4
    tables:
      common:
        - tcurr
  sapModuleCustNS:
    # Type of the dependent Module.
    # use cortex.sap if you followed "Configure multiple instances of a data foundation module"
    # https://docs.cloud.google.com/cortex/docs/deployment-configuration#multiple-data-foundation-instances
    type: cortex.sap
    # use sap_bookingdatamodel.sap if you are connecting to custom-data foundation module:
    # https://docs.cloud.google.com/cortex/docs/extensibility-guide-data-foundation
    #type: sap_bookingdatamodel.sap
    supported_versions:
      - ecc
      - s4
    tables:
      common:
        - sflight
builder: sap_product
  • En el siguiente paso, crea el archivo de configuración de la tabla al que se hace referencia para configurar el esquema y los metadatos de las tablas o vistas de salida en BigQuery.

En el ejemplo utilizado, crea: src/data_modules/custom_namespace/data_product/data_product_module_type/table_settings.default.yaml con el contenido:

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

  • Crea anotaciones para las tablas de productos de datos para enriquecer el esquema de almacenamiento con descripciones.

En el ejemplo utilizado, crea el archivo: src/data_modules/custom_namespace/data_product/data_product_module_type/annotations/flights_usd.yaml con el contenido:

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 lógica empresarial del producto de datos se almacena en archivos js o sqlx.

En el ejemplo dado, crea el archivo src/data_modules/custom_namespace/data_product/data_product_module_type/definitions/flights_usd.js con el contenido:

// ___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"])}
`
);

Verificación de la extensión del espacio de nombres personalizado

Para verificar la creación correcta de los módulos de productos de datos de Google Cloud Cortex Framework, sigue estos pasos: