このトピックでは、Resolveアノテーションを使用する場合に、MaxComputeのユーザー定義集計関数 (UDAF) とユーザー定義テーブル値関数 (UDTF) でサポートされる動的パラメーターについて説明します。
Resolveアノテーション構文の拡張
MaxCompute UDAFとUDTFはどちらも、Resolveアノテーションを使用して関数のシグネチャを生成します。 ただし、入力と出力のパラメーターが固定されているため、この方法ではオーバーロードできません。
@com.aliyun.odps.udf.annotation.Resolve("BIGINT->DOUBLE")
public class UDTFClass extends UDTF {
...
}
この例では、BIGINT型のパラメーターを受け取り、DOUBLE型の値を返すUDTFを定義します。
MaxComputeのResolveアノテーションの構文が拡張されました。
パラメーターリストでアスタリスク (
*
) を使用して、入力パラメーターの長さとタイプを指定できます。 たとえば、@ Resolve('double,*->String')
は、最初のパラメーターがDOUBLEデータ型で、その後に任意の長さと型のパラメーターが続くパラメーターリストを示します。 この場合、コードをコンパイルして入力パラメーターの数と種類を計算し、Cプログラミング言語のprintf
関数に基づいてそれらを管理する必要があります。説明戻り値のアスタリスク (*) は異なる意味を示します。
パラメータリストで
any
を使用して、すべての型のパラメータが有効であることを示すことができます。 たとえば、@ Resolve('double,any->string ')
は、最初のパラメーターがDOUBLEデータ型で、その後に任意の型のパラメーターが続くパラメーターリストを示します。説明any
は、ARRAYなどの複合データ型の戻り値またはサブタイプでは使用できません。UDTFの戻り値でアスタリスクを使用して、STRINGデータ型の任意の数の値を返すことができることを示すことができます。 戻り値の数は、関数が呼び出されたときに設定されるエイリアスの数に基づいています。 たとえば、
@ Resolve("ANY,ANY->DOUBLE,*")
の呼び出しメソッドは、UDTF(x, y) as (a, b, c)
です。 この例では、3つのエイリアスa、b、cがとして
設定されています。 エディタは、aがDOUBLEデータ型であり、bおよびcがSTRINGデータ型であることを識別する。 Resolveアノテーションで返される最初の列の値の型が指定されます。 3つの値が返されます。 したがって、UDTFによって呼び出されるforward
メソッドは、3つの要素の配列をforward
する必要があります。 それ以外の場合は、エラーが返されます。説明ただし、コンパイル中にエラーは返されません。 したがって、UDTFの呼び出し元は、UDTFで定義されているルールに基づいてSQLのエイリアスの数を設定する必要があります。 集計関数の戻り値の数は1に固定されています。 したがって、このルールはUDAFには影響しません。
UDTFの例
import com.aliyun.odps.udf.UDFException;
import com.aliyun.odps.udf.UDTF;
import com.aliyun.odps.udf.annotation.Resolve;
import org.json.JSONException;
import org.json.JSONObject;
@Resolve("STRING,*->STRING,*")
public class JsonTuple extends UDTF {
private Object[] result = null;
@Override
public void process(Object[] input) throws UDFException {
if (result == null) {
result = new Object[input.length];
}
try {
JSONObject obj = new JSONObject((String)input[0]);
for (int i = 1; i < input.length; i++) {
// The variable-length part of a return value must be of the STRING data type.
result[i] = String.valueOf(obj.get((String)(input[i])));
}
result[0] = null;
} catch (JSONException ex) {
for (int i = 1; i < result.length; i++) {
result[i] = null;
}
result[0] = ex.getMessage();
}
forward(result);
}
}
この例では、戻り値の数は入力パラメーターの数に基づいています。 最初の出力パラメーターはJSONファイルを示し、その他の出力パラメーターはJSONファイルから解析されたキーです。 最初の戻り値は、JSONファイルの解析中のエラーメッセージです。 エラーが発生しない場合、JSONファイルの解析中に生成されるコンテンツは、入力キーのシーケンスに基づいて提供されます。 例:
-- Configure the number of output aliases based on that of input parameters.
SELECT my_json_tuple(json, 'a', 'b') as exceptions, a, b FROM jsons;
-- The variable-length part can have no columns.
SELECT my_json_tuple(json) as exceptions, a, b FROM jsons;
-- An error occurs when the following SQL statement is executed because the number of aliases does not match the actual number.
-- This error is not returned during compilation.
SELECT my_json_tuple(json, 'a', 'b') as exceptions, a, b, c FROM jsons;
このトピックで説明する拡張機能がビジネス要件を満たしていない場合は、UDTを使用して集計関数とUDTFの機能を実装することを推奨します。 詳細については、「概要」をご参照ください。
Python UDTFおよびPython UDAFの詳細については、「Python 3 UDAF」および「Python 3 UDTFを使用してMaxComputeからリソースを読み取る」をご参照ください。