S-JIS[2013-11-12/2016-02-11] 変更履歴

Asakusa Framework 分割演算子

Asakusa FrameworkOperator DSLの分割演算子(@Split)のメモ。


概要

分割演算子は、結合モデル(マスター結合演算子の出力)を結合元のデータモデルに分解する演算子。
性能特性はExtract(旧ドキュメントではMap)。[/2016-02-11]

入力
ポート数
入力データモデル
の制約
イメージ 出力
ポート数
出力データモデル
の制約
入力1レコード
に対する
出力レコード数
1 結合モデル 2 left inの元の
データモデル
1レコード。
right inの元の
データモデル
1レコード。

(結合モデルを元のデータモデルに分割する以外で)入力データモデルを別のデータモデルに変換する場合は変換演算子(@Convert)抽出演算子(@Extract)を使う。


joined_hogeという結合モデルを元のhoge_masterとhoge_transactionに分割する例。
(この図はToad Editorを用いて作っています)

入力データ例   出力データ例
in
joined_hoge
id name group date master_id value
a apple 1 2013-11-29 a 123
b orange 2 2013-11-29 b 456
d game 101 2013-11-29 d 789
e other 900 2013-11-29 e 111
master
hoge_master
id name group
a apple 1
b orange 2
d game 101
e other 900
tx
hoge_transaction
date master_id value
2013-11-29 a 123
2013-11-29 b 456
2013-11-29 d 789
2013-11-29 e 111

example.dmdl(DMDL):

hoge_master = {

    id : TEXT;

    name : TEXT;
};

hoge_transaction = {

    date : DATE;

    master_id : TEXT;

    value : LONG;
};

joined joined_hoge = hoge_master % id + hoge_transaction % master_id;

ExampleOperator.java(Operator DSL):

import com.asakusafw.runtime.core.Result;
import com.asakusafw.vocabulary.operator.Split;

import com.example.modelgen.dmdl.model.HogeMaster;
import com.example.modelgen.dmdl.model.HogeTransaction;
import com.example.modelgen.dmdl.model.JoinedHoge;
public abstract class ExampleOperator {

	/**
	 * JoinedHogeを分割する
	 * 
	 * @param joined
	 *         分割するレコード
	 * @param master
	 *         分割後のHogeMaster
	 * @param tx
	 *         分割後のHogeTransaction
	 */
	@Split
	public abstract void split(
		JoinedHoge in,
		Result<HogeMaster>      master,
		Result<HogeTransaction> tx
	);
}

分割演算子は抽象メソッドとして定義する。
第1引数で結合モデル、第2引数と第2引数で分割して出力されるデータモデル(結合前のデータモデル)を指定する。
戻り型は無し。

ExampleJob.java(Flow DSL):

import com.example.modelgen.dmdl.model.HogeMaster;
import com.example.modelgen.dmdl.model.HogeTransaction;
import com.example.modelgen.dmdl.model.JoinedHoge;

import com.example.operator.ExampleOperatorFactory;
import com.example.operator.ExampleOperatorFactory.SplitFields;
	private final In<JoinedHoge> in;

	private final Out<HogeMaster>      out1;
	private final Out<HogeTransaction> out2;
	@Override
	public void describe() {
		ExampleOperatorFactory operators = new ExampleOperatorFactory();

		// joined_hogeを分割する
		Split split = masterOperator.split(this.in);

		this.out1.add(split.master);
		this.out2.add(split.tx);
	}

Flow DSLでは、自分が作ったOperatorのFactoryクラス(AsakusaFWのコンパイラーによって生成される)を使用する。
メソッド名はOperatorクラスに書いたメソッド名と同じ。
戻り値の型はAsakusaFWのコンパイラーによって生成されたクラス。(メソッド名を先頭が大文字のキャメルケースに変換したもの)

出力ポートの名前は、Operatorクラスのメソッドに出力ポート(Result<データモデル>)として指定した変数名が使われる。


単体テスト

分割演算子は抽象メソッドなので、(Operatorクラスにプログラマーがメソッド本体を実装していないので)Operatorの単体テストを実装する必要は無い。


類似

分割演算子は、Scalaunzipメソッドと概念的には似ている 。

//「StringとIntのペア」のListを、StringのList と IntのListに分割する

scala> val joined = List(("a", 123), ("b", 456), ("c", 789))
joined: List[(String, Int)] = List((a,123), (b,456), (c,789))

scala> val (left, right) = joined.unzip
left: List[String] = List(a, b, c)
right: List[Int] = List(123, 456, 789)

Operator DSLへ戻る / AsakusaFW目次へ戻る / 技術メモへ戻る
メールの送信先:ひしだま