10. CSVフォーマットの定義¶
このチュートリアルでは DMDL を利用してAsakusa Frameworkで利用する データモデル を定義する方法を説明していきます。
結合モデルと集計モデルの定義 の続きで、ここではバッチアプリケーションからCSVフォーマットのファイルを読み書きするための定義を追加していきます。
10.1. 外部入出力に利用するデータモデル¶
これまでのチュートリアルで6つのデータモデルを作成してきましたが、これらのデータモデルをその用途によって分類してみます。 サンプルアプリケーションの説明 のデータフロー図も合わせて参考にしてください。
- 入力データとなるファイルに対応するデータモデル
- 出力データとなるファイルに対応するデータモデル
- バッチ処理の処理途中のデータを格納するデータモデル
このうち「入力データとなるファイルに対応するデータモデル」と「出力データとなるファイルに対応するデータモデル」を外部入出力に利用するデータモデルとして利用します。
Asakusa Frameworkには、分散ファイルシステム上に配置したデータに対して Direct I/O というデータ入出力機能を利用してデータを読み書きすることができます。 このチュートリアルではDirect I/Oを使って上記のデータモデルに対応するCSVファイルを読み書きできるように定義していきます。
なお「バッチ処理の処理途中のデータを格納するデータモデル」はデータフロー内の中間データを保持するために利用するデータモデルです。 外部入出力に利用するデータモデルと区別するためにこれを「中間モデル」や「中間データモデル」などと呼ぶことがあります。
上図が示す通り、 売上明細 ( sales_detail ) は外部入力用のデータモデルと中間データモデルの2つの用途で使用しています。 また、 結合モデル ( joined_sales_info ) は中間データモデルとしてのみ使用するため、外部入出力用の定義は不要です。
10.2. Direct I/O CSVのフォーマット情報を定義する¶
ここでは 売上明細 ( sales_detail ) のデータモデルに対して、Direct I/O CSVのフォーマット情報定義を追加する過程を説明していきます。
データモデルをDirect I/O CSVと連携させるには対象となるデータモデル定義に @directio.csv
属性を指定します。
"売上明細"
@directio.csv
sales_detail = {
...
};
@directio.csv
属性には、CSVフォーマットに関する様々な設定を定義することができます。
前項の サンプルアプリケーションの説明 - データフォーマット では、CSVフォーマットについて以下のような仕様が定義されていました。
- 各CSVファイルの文字エンコーディングはUTF-8として扱う。
- 各CSVファイルの1行目は各項目の内容を示すヘッダとして扱い、実データとしては扱わない。
- 各CSVファイルの日付項目のフォーマットは
yyyy-MM-dd
、日時項目のフォーマットはyyyy-MM-dd HH:mm:ss
とする。
この仕様に沿って @directio.csv
属性にフォーマットに関する指定を追加します。
"売上明細"
@directio.csv (
charset = "UTF-8",
has_header = TRUE,
date = "yyyy-MM-dd",
datetime = "yyyy-MM-dd HH:mm:ss"
)
sales_detail = {
...
};
@directio.csv
後ろに (...)
で囲ったブロックを追加し、この中に設定項目の要素を定義します。要素間は ,
で区切ります。
charset
はファイルの文字エンコーディングを指定します。既定値は UTF-8
であるため設定しなくても同じ動作になります。
has_header
を有効にすることで、1行目をヘッダとして扱います。
このオプションを有効にしている場合にデータモデルの各プロパティに対して @directio.csv.field
属性を指定することで以下のように動作します。
- ファイル入力時:指定したヘッダ名と入力ファイルが持つヘッダ名が一致するかをチェックする
- ファイル出力時:指定したヘッダ名で出力ファイルのヘッダを生成する
date
, datetime
はそれぞれ DATE
型、 DATETIME
型の表現形式を指定します。
続けてデータモデルの各プロパティに対して @directio.csv.field
属性を追加して、ヘッダ名を指定します。
"売上明細"
@directio.csv (
charset = "UTF-8",
has_header = TRUE,
date = "yyyy-MM-dd",
datetime = "yyyy-MM-dd HH:mm:ss"
)
sales_detail = {
"売上日時"
@directio.csv.field(name = "日時")
sales_date_time : DATETIME;
"店舗コード"
@directio.csv.field(name = "店舗コード")
store_code : TEXT;
...
};
また @directio.csv.file_name
属性を指定したプロパティは、ファイル入力時のファイル名を格納します。
sales_detail = {
...
"ファイル名"
@directio.csv.file_name
file_name : TEXT;
};
今回のアプリケーションでは、入力となる売上明細のファイル名をデータモデルとして保持しておき、 売上明細のエラーチェック時に、該当したレコードが含まれるファイル名をエラー情報に受け渡します。
なお、この属性を指定したプロパティはCSVフィールドとしては扱われないため、 CSVファイルフォーマットに関係なく入力ファイル名を保持することができます。
売上明細 ( sales_detail ) の最終的なデータモデル定義は、以下のようになります。
"売上明細"
@directio.csv(
has_header = TRUE,
datetime = "yyyy-MM-dd HH:mm:ss"
)
sales_detail = {
"売上日時"
@directio.csv.field(name = "日時")
sales_date_time : DATETIME;
"店舗コード"
@directio.csv.field(name = "店舗コード")
store_code : TEXT;
"商品コード"
@directio.csv.field(name = "商品コード")
item_code : TEXT;
"数量"
@directio.csv.field(name = "数量")
amount : INT;
"販売単価"
@directio.csv.field(name = "販売単価")
unit_selling_price : INT;
"販売金額"
@directio.csv.field(name = "販売金額")
selling_price : INT;
"ファイル名"
@directio.csv.file_name
file_name : TEXT;
};
同様の手順で models.dmdl
に含まれる以下のデータモデルにDirect I/O CSVのフォーマット情報を定義しましょう。
10.3. 終わりに¶
全てのデータモデルを定義した後にデータモデルクラスの生成を行い、6つのデータモデルの生成が成功していることをコンソールで確認してください。
このチュートリアル終了時点のDMDLスクリプト models.dmdl
は、次のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | "売上明細"
@directio.csv(
has_header = TRUE,
datetime = "yyyy-MM-dd HH:mm:ss"
)
sales_detail = {
"売上日時"
@directio.csv.field(name = "日時")
sales_date_time : DATETIME;
"店舗コード"
@directio.csv.field(name = "店舗コード")
store_code : TEXT;
"商品コード"
@directio.csv.field(name = "商品コード")
item_code : TEXT;
"数量"
@directio.csv.field(name = "数量")
amount : INT;
"販売単価"
@directio.csv.field(name = "販売単価")
unit_selling_price : INT;
"販売金額"
@directio.csv.field(name = "販売金額")
selling_price : INT;
"ファイル名"
@directio.csv.file_name
file_name : TEXT;
};
"店舗マスタ"
@directio.csv(
has_header = TRUE
)
store_info = {
"店舗コード"
@directio.csv.field(name = "店舗コード")
store_code : TEXT;
"店舗名称"
@directio.csv.field(name = "名称")
store_name : TEXT;
};
"商品マスタ"
@directio.csv(
has_header = TRUE,
date = "yyyy-MM-dd"
)
item_info = {
"商品コード"
@directio.csv.field(name = "商品コード")
item_code : TEXT;
"商品名"
@directio.csv.field(name = "商品名")
item_name : TEXT;
"商品部門コード"
@directio.csv.field(name = "部門コード")
department_code : TEXT;
"商品部門名"
@directio.csv.field(name = "部門名")
department_name : TEXT;
"商品カテゴリコード"
@directio.csv.field(name = "カテゴリコード")
category_code : TEXT;
"商品カテゴリ名"
@directio.csv.field(name = "カテゴリ名")
category_name : TEXT;
"商品単価"
@directio.csv.field(name = "単価")
unit_selling_price : INT;
"マスタ登録日"
@directio.csv.field(name = "登録日")
registered_date : DATE;
"マスタ適用開始日"
@directio.csv.field(name = "適用開始日")
begin_date : DATE;
"マスタ適用終了日"
@directio.csv.field(name = "適用終了日")
end_date : DATE;
};
"売上明細+商品マスタ"
joined joined_sales_info
= sales_detail -> {
"商品コード"
item_code -> item_code;
"販売数量"
amount -> amount;
"売上合計"
selling_price -> selling_price;
} % item_code
+ item_info -> {
"商品コード"
item_code -> item_code;
"カテゴリコード"
category_code -> category_code;
} % item_code;
"カテゴリ別売上集計"
@directio.csv(
has_header = TRUE
)
summarized category_summary = joined_sales_info => {
"カテゴリコード"
@directio.csv.field(name = "カテゴリコード")
any category_code -> category_code;
"販売数量"
@directio.csv.field(name = "販売数量")
sum amount -> amount_total;
"売上合計"
@directio.csv.field(name = "売上合計")
sum selling_price -> selling_price_total;
} % category_code;
"エラー情報"
@directio.csv(
has_header = TRUE,
datetime = "yyyy-MM-dd HH:mm:ss"
)
error_record = {
"ファイル名"
@directio.csv.field(name = "ファイル名")
file_name : TEXT;
"売上日時"
@directio.csv.field(name = "日時")
sales_date_time : DATETIME;
"店舗コード"
@directio.csv.field(name = "店舗コード")
store_code : TEXT;
"商品コード"
@directio.csv.field(name = "商品コード")
item_code : TEXT;
"エラーメッセージ"
@directio.csv.field(name = "メッセージ")
message : TEXT;
};
|