データ プロダクト モジュールの作成

独自のビジネス ロジックと分析モデルを定義するには、カスタムのデータ プロダクト モジュールを作成します。これにより、基盤テーブルまたはアップストリーム データ プロダクトで計算を実行し、結果をデプロイ可能なデータセットにパッケージ化できます。

前提条件

ライフサイクル管理を改善するために、専用のカスタム名前空間にカスタム データ プロダクト モジュールを作成することをおすすめします。また、使用する予定のソーステーブルがデータ基盤データセットに存在することを確認します。

データ プロダクト モジュールの作成

データ プロダクト モジュールの定義には、次の手順が必要です。

  • config/config.yaml ファイル内のデータ プロダクト モジュールの登録。data.modules.products リストをエントリで拡張します。
data:
  # Configuration for data foundation and product modules.
  modules:
    # List of data product modules.
    products:
        # Recommended naming for product_module_id:
        # custom_namespace_product_name
      - moduleId:  product_module_id
        # Path of the data product (namespaced).
        modulePath:  custom_namespace.system_type.products.product_name
        # Map of module dependencies.
        dependencyBindings:
          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}/{system_type}/products/{product_name}/table_settings.yaml'
        # If omitted, defaults to '../src/data_modules/{custom_namespace}/{system_type}/products/{product_name}/table_settings.default.yaml'
        # tableSettings: "{custom_namespace}/{system_type}/products/{product_name}/table_settings.yaml"
        
  • デフォルトの tableSettings ファイルsrc/data_modules/custom_namespace/system_type/products/product_name/table_settings.default.yaml など)の作成。

この YAML は、マテリアライズや BigQuery の最適化の詳細などのテーブル構成を制御します。

common:
  custom_sales_summary:
    materializationType: "table"
    bigQueryLabels:
      - key: data_class
        value: transactional
    dataformTags: ["custom", "sales", "reporting"]
    partitionDetails:
      column: "created_date"
      partitionType: "date"
      timeGrain: "day"
    clusterDetails:
      columns:
        - "customer_id"
  • アノテーション ファイルの作成

アノテーション ファイル tablename.yaml は、各データ プロダクト出力アーティファクト(テーブル、ビュー)に対して作成され、YAML 形式で列とフィールドを記述します。コンパイル中に、ビルダーはプロダクトの annotations/ フォルダ(src/data_modules/custom_namespace/system_type/products/product_name/annotations/custom_sales_summary.yaml など)内のアノテーションを自動的に検索し、これらの文字列を出力 Dataform スキーマ定義に直接マージして、BigQuery テーブルのメタデータに保持します。

アノテーション src/data_modules/custom_namespace/system_type/products/product_name/annotations/tablename.yaml ファイルの形式は次のとおりです。

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"
  • データ プロダクト フォルダ src/data_modules/custom_namespace/system_type/products/product_name/manifest.yaml ファイルを作成し、型、カテゴリ、テーブル、モジュールの依存関係を維持します。マニフェスト ファイルの形式は次のとおりです。
displayName: Sales Performance Summary
description: Sales performance analytical data product.
category: product
type: generic
builder: sap_product     # Automatically resolves to the global SapProductBuilder fallback
dependencies:
  sapModule:
    modulePath: cortex.sap.foundations.sap
    supportedVersions:
      - ecc
      - s4

データ プロダクト モジュールの例

フライトの例の Namespace sap_bookingdatamodelflights_usd データ プロダクトを実装する手順は次のとおりです。

  • config/config.yaml ファイル内のデータ プロダクト モジュールの登録。data.modules.products リストをエントリで拡張します。
data:
  modules:
    products:
      - moduleId: sap_bookingdatamodel_flights_usd
        modulePath: sap_bookingdatamodel.sap.products.flights_usd
        dependencyBindings:
          sapModule: erp
          sapModuleCustNS: sap_bookingdatamodel
        dataTargetId: product_target
  • 次に、次の内容で src/data_modules/sap_bookingdatamodel/sap/products/flights_usd/manifest.yaml を作成します。
displayName: Flights USD
description: Flight scheduling and pricing USD data product.
category: product
type: generic
dependencies:
  sapModule:
    modulePath: cortex.sap.foundations.sap
    supportedVersions:
      - ecc
      - s4
    tables:
      common:
        - tcurr
  sapModuleCustNS:
    # Type of the dependent Module.
    # use cortex.sap.foundations.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
    modulePath: cortex.sap.foundations.sap
    # use sap_bookingdatamodel.sap.foundations.sap if you are connecting to custom-data foundation module:
    # https://docs.cloud.google.com/cortex/docs/extensibility-guide-data-foundation
    #modulePath: sap_bookingdatamodel.sap.foundations.sap
    supportedVersions:
      - ecc
      - s4
    tables:
      common:
        - sflight
builder: sap_product
  • 次のステップでは、参照されるテーブル設定ファイルを作成して、BigQuery の出力テーブルまたはビューのスキーマとメタデータを構成します。

使用した例では、次の内容で src/data_modules/sap_bookingdatamodel/sap/products/flights_usd/table_settings.default.yaml を作成します。

ecc:
  flights_usd:
    materializationType: incremental
    bigQueryLabels:
      - key: data_class
        value: transactional
    dataformTags: [sap, dataproduct, masterdata]
s4:
  flights_usd:
    materializationType: incremental
    bigQueryLabels:
      - key: data_class
        value: transactional
    dataformTags: [sap, dataproduct, masterdata]

  • データ プロダクト テーブルのアノテーションを作成して、説明でストレージ スキーマを拡充します。

使用した例では、次の内容の src/data_modules/sap_bookingdatamodel/sap/products/flights_usd/annotations/flights_usd.yaml ファイルを作成します。

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"
  • データ プロダクトのビジネス ロジックは、js ファイルまたは sqlx ファイルに保存されます。

次の例では、次の内容の src/data_modules/sap_bookingdatamodel/sap/products/flights_usd/definitions/flights_usd.js ファイルを作成します。

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

カスタム Namespace 拡張機能の検証

Google Cloud Cortex Framework データ プロダクト モジュールが正常に作成されたことを確認する手順は次のとおりです。