Talend入門 (5)　～イテレータ～

##全体の目的
Talendの超簡単なサンプルジョブを作成して，ETLジョブ開発に必要なスキルを習得することが目的です。

##対象者
ETL / EAI技術者

##環境
|使用環境|バージョン|
|:----:|:------------------|
|OS|Windows10|
|Talend|7.1.1|	

##サンプル一覧
以下の順番で習得していきます

|#|内容|
|:----:|:------------------|
|1|[はじめてのTalend](https://qiita.com/airkoda/items/a837d3c5d851d98d2612)|
|2|[ファイルI/O](https://qiita.com/airkoda/items/1cd12c05c6136add7178)|
|3|[データベースI/O](https://qiita.com/airkoda/items/bc807c920c3adebad837)|
|4|[tMap](https://qiita.com/airkoda/items/fa4a9c022b5d688698e0)|
|**5**|**[イテレータ（今回）](https://qiita.com/airkoda/items/404d2d65eff535b2126c)**|
|6|[メタデータ](https://qiita.com/airkoda/items/4b42cf2a86f34abb6c87)|
|7|[Context変数](https://qiita.com/airkoda/items/42d294fca40b81aa20fb)|
|8|[Global Map](https://qiita.com/airkoda/items/1aba0d36905c755deeae)|
|9|[tHashInput/tHashOutput](https://qiita.com/airkoda/items/d9347865190f0f3ab180)|
|10|[エラーハンドリング](https://qiita.com/airkoda/items/85e7c49a9bf6a21db6d5)|
|11|[ロギング](https://qiita.com/y-fujioka-yoshiharu/items/e0280f34cff2e3d00bda)|
|12|[子ジョブ（ジョブのネスト）](https://qiita.com/y-fujioka-yoshiharu/items/04ea4bd74ded382cf03c)|
|13-1|[設定ファイル読み込みオリジナル版](https://qiita.com/airaotaku/items/92f114795108f25e6d0f)|
|13-2|[設定ファイル読み込みコンポ版](https://qiita.com/airyama/items/83c2bf9b2d51a79c3714)|
|14|[tJava](https://qiita.com/airkoda/items/4d81d76c36b6fcbd4d89)|

[サンプルコード（Talendプロジェクトデータ）](https://github.com/kd2air/qiita)

##今回の目的
イテレータを理解する

##サンプルプログラム概要
複数ファイルにわかれた経費伝票を社員毎にまとめる処理を実装してみます。

![GS000139.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/2dfa3d93-8121-7981-f813-62d10de65760.png)

##反復処理を理解する
以下の流れで実装します。

- tFileListでイテレータを理解
    - 複数の入力ファイルの内容を一つのファイルにまとめる
- ユニークデータを生成
- ユニークデータ単位でloop
    - ファイルを生成
    - 対象データのみを出力

### 入力ファイル準備
C:/work/Iteration 配下に次の3ファイルを準備します。(UTF-8,LFで作成)
![GS000140.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/c21b4751-2bb7-3e71-d008-3d3aaa6f8d29.png)


```csv:exp_20190410.csv
2019/04/10,koda,交際費,20000
```

```csv:exp_20190411.csv
2019/04/11,kubo,宣伝費,100000
2019/04/11,mori,交通費,800
2019/04/11,mori,雑費,3000
```

```csv:exp_20190412.csv
2019/04/12,koda,メモリ,4000
2019/04/12,mori,通信費,5200
```

### tFileList
それではサンプルジョブを作成していきましょう。
リポジトリの[ジョブ]を右クリックし[ジョブの作成]を選択します。
[名前]に**iteration**と入力し[Finish]ボタンをクリックします。

![GS000141.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/19e46e26-2bff-c0e4-c5bf-a1a2d0aad65d.png)

[tFileList]コンポーネントを配置しパラメータを設定します。

![GS000142.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/9108e03e-8e56-2c12-eba4-f7ab8e1a78bc.png)

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| ディレクトリ  | "C:/work/Iteration" |  |
| ファイルマスク  | "*.csv" | 拡張子csvだけを読み込む |

[tFileInputDelimited]コンポーネントを配置しパラメータを設定します。

![GS000145.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/ce736c48-6646-a18c-3517-638637df0df5.png)

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| ファイル名  | ((String)globalMap.get("tFileList_1_CURRENT_FILEPATH")) | Global Mapは第8回で別途説明しますので今回はコピペで。 |
| フィールド区切り  | ","|  |
| エンコーディング  | UTF-8 | 詳細設定タブ |
| スキーマ編集  | 下記 | 下記参照 |

![GS000144.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/5eab9349-7635-4a3c-4de1-cd62963eeb35.png)

| 列      | カラム |  タイプ |
|:-----------------|:------------------|:------------------|
| 1列目    | date  | Date "yyyy/MM/dd" |
| 2列目    | name  | String|
| 3列目    | expense  | String|
| 3列目    | amount  | BigDecimal|


[tFileList]コンポーネントを右クリックし[ロウ]-[反復]を選び[tFileInputDelimited]につなぎます。

![GS000145b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/7c09d3b1-750a-4579-5282-ab63eee1e48b.png)
![GS000146.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/79e3b766-6c32-78c6-1df9-be63cdb323b3.png)

ここで[tLogRow]を配置し一度出力を確認してみましょう。すべてのcsvファイル読込みを確認できました。

![GS000147.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/9ed2103a-ef9e-e000-648a-75f38f148839.png)

マージファイルを作成するために[tFileOutputDelimited]コンポーネントを配置しパラメータを設定します。
![GS000148.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/fe3d8554-5bbf-3629-eb1b-361bf523b829.png)

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| ファイル名  | "C:/work/Iteration/merge.dat" | |
| フィールド区切り  | ","|  |
| 追加  | チェック |  |
| エンコーディング  | UTF-8 | 詳細設定タブ |

[tLogRow]と[tFileOutputDelimited]をロウをつなぎ実行します。
merge.datが作成できました。

![GS000150.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/c21e11d9-734b-b049-1caa-b19d164e5906.png)

#### ファイル削除処理
このままだとmerge.datが実行するたびに追記されてしまうので処理前に削除するようにしておきます。
[tFileDelete]コンポーネントを以下パラメータで配置します。

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| ファイル名  | "C:/work/Iteration/merge.dat" | |
| エラーで失敗  | チェックを外す |  |

[tFileDelete]コンポーネントを右クリックし[トリガー]-[サブジョブがOKの場合]を選び最初に配置した[tFileList]につなぎます。

![GS000150b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/c137dd0f-0b51-d3df-8827-5f6d413fd27c.png)
![GS000151.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/986bc040-8032-4a64-8e8a-cdea71d5c6c7.png)

毎回削除（初期化）されているか念のため実行確認しておきましょう。

### 社員毎のユニークデータを生成

[tFileInputDelimited]コンポーネントを配置しパラメータを設定します。
※最初の[tFileInputDelimited_1]をコピペすると楽です。

![GS000153.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/1100e854-f925-233a-f3dd-7b896407d70f.png)

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| ファイル名  | "C:/work/Iteration/merge.dat" | |
| フィールド区切り  | ","|  |
| エンコーディング  | UTF-8 | 詳細設定タブ |
| スキーマ編集  | 上記参照 | [tFileInputDelimited]と同じ |

[tFileList_1]コンポーネントを右クリックし[トリガー][サブジョブがOKの場合]を選び[tFileInputDelimited_2]につなぎます。

[tUniqRow]を配置し、[tFileInputDelimited_2]とロウでつなぎます。
そのうえでパラメータを設定します。

![GS000154.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/2095a658-93ed-437b-8e25-8b80581ceffc.png)

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| ユニークなキー  | nameのキー属性にチェック | |

ここで[tLogRow]を配置し[tUniqRow]とつないだうえで一度出力を確認してみましょう。nameでユニークなデータを作れたことが確認できます。

![GS000155.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/6f519f08-b784-9ad4-925c-68ed39d08b82.png)

#### ロウ毎にイテレート
本日2回目のイテレートの登場です。
[tFlowToIterate]コンポーネントを配置し[tLogRow_2]とロウでつなぎます。
これでname毎のloop処理ができます。

![GS000156.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/7e0563ff-024d-4801-3001-edc2fe199e3d.png)

再度merge.datを読み込みます。
[tFileInputDelimited_3]は[tFileInputDelimited_2]と同じ内容なのでコピペでＯＫです。
![GS000157.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/0216181a-6055-3b7a-c8f6-4f29a0a9f3c9.png)

[tFlowToIterate_1]コンポーネントを右クリックし[ロウ]-[反復]を選び[tFileInputDelimited_3]につなぎます。

name単位の処理をするために[tMap]コンポーネント配置し[tFileInputDelimited_3]とロウをつなぎます。

![GS000158.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/9ff6f0d5-ecc0-2b08-4f72-a8876838ca7e.png)

[tMap]をダブルクリックし、マッピング設定画面を開きます。
row6の式フィルターボタンをクリックし式を記入します。

![GS000159.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/fc760f17-673f-120a-ad61-c17170c64afc.png)

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| row6の式フィルタ  | row6.name.equals( ((String)globalMap.get("row5.name")) ) | イテレート処理中のnameとマッチさせる|

出力用のロウout1を作成します。

![GS000160.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/9ef4df2a-f783-fff1-913a-1fb951efcd82.png)

ここで[tLogRow]を配置し[tMap]のout1ロウとつないだうえで実行して出力を確認してみましょう。
name単位で経費明細を抽出できたことをログ出力で確認できます。

![GS000161.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/f5f70559-1c65-46da-2f5d-b2790e6fdd91.png)

```
.----------+----+-------+------.
|          tLogRow_3           |
|=---------+----+-------+-----=|
|date      |name|expense|amount|
|=---------+----+-------+-----=|
|2019/04/10|koda|交際費    |20000 |
|2019/04/12|koda|メモリ    |4000  |
'----------+----+-------+------'
.----------+----+-------+------.
|          tLogRow_3           |
|=---------+----+-------+-----=|
|date      |name|expense|amount|
|=---------+----+-------+-----=|
|2019/04/11|kubo|宣伝費    |100000|
'----------+----+-------+------'
.----------+----+-------+------.
|          tLogRow_3           |
|=---------+----+-------+-----=|
|date      |name|expense|amount|
|=---------+----+-------+-----=|
|2019/04/11|mori|交通費    |800   |
|2019/04/11|mori|雑費     |3000  |
|2019/04/12|mori|通信費    |5200  |
'----------+----+-------+------'
```

ここまで来たらあとは実際のファイルに出力するだけです。
[tFileOutputDelimited_2]コンポーネントを配置しパラメータを設定します。
※[tFileOutputDelimited_1]をコピペすると楽です。

![GS000162.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/43403d30-6fcf-7a13-adbe-cf54cde84885.png)

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| ファイル名  | "C:/work/Iteration/out_"+ ((String)globalMap.get("row5.name"))+".dat" | |
| フィールド区切り  | ","|  |
| エンコーディング  | UTF-8 | 詳細設定タブ |
| スキーマ編集  | 上記参照 |  |

それでは実行してみましょう。
name(従業員名)毎のファイルを作成できました。

![GS000163.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/71db189f-8859-7b7b-3a03-51ba60e929bd.png)

```csv:out_koda.dat
2019/04/10,koda,交際費,20000
2019/04/12,koda,メモリ,4000
```

```csv:out_kubo.dat
2019/04/11,kubo,宣伝費,100000
```

```csv:out_mori.dat
2019/04/11,mori,交通費,800
2019/04/11,mori,雑費,3000
2019/04/12,mori,通信費,5200
```

#### 仕上げ
同じジョブを複数回実行してもファイルの都度上書きが起こらないよう対応しましょう。
出力ファイルの初期化処理を設定します。

[tFileDelete]コンポーネントを配置しパラメータを設定します。

![GS000165.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/4daa63b7-e989-0e7f-24f8-6cce6bd3924e.png)

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| ファイル名  | "C:/work/Iteration/out_"+ ((String)globalMap.get("row5.name"))+".dat" | |
| エラーで失敗  | チェックを外す |  |

[tFlowToIterate_1]と[tFileInputDelimited_3]の間に割り込ませます。
[tFileDelete_2]と[tFileInputDelimited_3]は[トリガー][コンポーネントがOKの場合]の線でつなぎます。

最後に[tLogRow]の出力も不要なので止めてしまいましょう。
[tLogRow]で右クリックし[無効化]を選択します。

![GS000165b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/dc3d4225-114f-c49d-ab9b-6c26f534ceff.png)

![GS000166.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364565/22441212-ec89-b8a7-d5dd-3f9d8522cd73.png)

##まとめ
今回はイテレータの使い方を確認しました。
ロウとイテレータの使い分けで様々なデータ生成ができることをわかってもらえたと思います。
あらたに利用したコンポーネントと用途をおさらいしておきます。

- tFileList
    - ファイル一覧取得
- tFileDelete
    - ファイル削除
- tUniqRow
    - キーを指定してユニークロウを作る
- tFlowToIterate
    - 文字通りなんですが、ロウデータをイテレータに変換すると覚えておけばOK

毎度のことですが、ほんのさわりの部分だけを解説していますのでぜひここから深掘りしてみてください。

##次回以降
次回はメタデータをやっていきます。