데이터 제품 모듈 만들기
자체 비즈니스 로직 및 분석 모델을 정의하려면 커스텀 데이터 제품 모듈을 만드세요. 이렇게 하면 기본 테이블 또는 업스트림 데이터 제품에서 계산을 실행하고 결과를 배포 가능한 데이터 세트로 패키징할 수 있습니다.
기본 요건
수명 주기 관리를 개선하려면 전용 커스텀 네임스페이스에서 커스텀 데이터 제품 모듈을 만드는 것이 좋습니다. 또한 사용하려는 소스 테이블이 데이터 기본 데이터 세트에 있는지 확인합니다.
데이터 제품 모듈 만들기
데이터 제품 모듈 정의에는 다음 단계가 필요합니다.
config/config.yaml파일 내에서data.modules.products목록을 항목으로 확장하여 데이터 제품 모듈을 등록합니다.
[...]
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.data_product_module_type
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/data_product_module_type/`
# If omitted, defaults to src/data_modules/custom_namespace_path/data_product/table_settings.default.yaml.
[...]
tableSettings파일 (예:config/custom_namespace_path/data_product/data_product_module_type/table_settings.yaml)을 만듭니다.
이 YAML은 테이블 구성과 같은 구체화 및 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"
- 주석 파일을 만듭니다.
주석 파일 <tablename>.yaml은 각 데이터 제품 출력 아티팩트 (테이블, 뷰)에 대해 생성되며 YAML 형식으로 열과 필드를 설명합니다. 컴파일 중에 빌더는 제품의 annotations/ 폴더 (예: annotations/custom_sales_summary.yaml) 내에서 주석을 자동으로 검색하고 이러한 문자열을 출력 Dataform 스키마 정의에 직접 병합하여 BigQuery 테이블 메타데이터에 보존되도록 합니다.
주석 config/custom_namespace_path/data_product/data_product_module_type/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"
- 유형, 테이블, 모듈 종속 항목을 유지하면서 데이터 제품 폴더
config/custom_namespace_path/data_product/data_product_module_type/에manifest.yaml파일을 만듭니다. 매니페스트 파일은 다음 형식을 따릅니다.
type: sales_performance
builder: sap_product # Automatically resolves to the global SapProductBuilder fallback
dependencies:
sapModule:
type: sap
supportedVersions:
- ecc
- s4
데이터 제품 모듈 예시
항공편 예시에서는 콘텐츠가 포함된 src/data_modules/custom_namespace_path/data_product/data_product_module_type/manifest.yaml을 만듭니다.
type: data_product_module_type
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
- 다음 단계에서는 데이터 제품 테이블의 참조된 테이블 설정 파일을 확장합니다.
사용된 예시에서 콘텐츠가 포함된 config/custom_namespace_path/data_product/data_product_module_type/table_settings.yaml을 만듭니다.
ecc:
flights_usd:
materializationType: incremental
tags: [sap, dataproduct, masterdata]
s4:
flights_usd:
materializationType: incremental
tags: [sap, dataproduct, masterdata]
- 데이터 제품 테이블의 주석을 만들어 설명으로 스토리지 스키마를 보강합니다.
사용된 예시에서 콘텐츠가 포함된 src/data_modules/custom_namespace_path/data_product/data_product_module_type/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/custom_namespace_path/data_product/data_product_module_type/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"])}
`
);
커스텀 네임스페이스 확장 확인
Google Cloud Cortex Framework 데이터 제품 모듈이 성공적으로 생성되었는지 확인하려면 다음 단계를 따르세요.
- 업데이트된
config.yaml파일을 참조하여 Cortex Framework 배포를 실행합니다. - 배포 후 단계에 따라 Dataform 작업을 실행하고 BigQuery에서 결과를 확인합니다.
- 이전 단계: 데이터 기본 모듈 만들기
- 다음 단계: 배포 후 단계
- 개요로 돌아가기