全部產品
Search
文件中心

MaxCompute:UDAF和UDTF動態參數說明

更新時間:Jun 19, 2024

本文為您介紹MaxCompute的UDAF和UDTF使用Resolve註解時支援的動態參數文法。

Resolve註解文法擴充

MaxCompute的UDAF和UDTF使用Resolve註解決定函數的Signature,樣本如下。這種方式的局限性在於輸入參數和輸出參數是固定的,無法實現方法重載。
@com.aliyun.odps.udf.annotation.Resolve("BIGINT->DOUBLE")
public class UDTFClass extends UDTF {
    ...
}
說明 樣本定義了一個UDTF,該UDTF接受的參數類型為BIGINT,傳回值類型為DOUBLE。
現在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),此處as後面設定了三個別名,即a、b、c。編輯器會認定a為DOUBLE類型(Annotation中傳回值第一列的類型是給定的),b和c為STRING類型。因為這裡給出了三個傳回值,所以UDTF在調用forward時,必須forward長度為3的數組,否則會出現運行時報錯。
    說明 這種錯誤無法在編譯時間報出,因此UDTF的調用者在SQL中設定alias個數時,必須遵循該UDTF定義的規則。由於彙總函式的傳回值個數固定是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++) {
        // 傳回值要求變長部分都是STRING。
        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);
  }
}
以上UDTF樣本中,傳回值個數會根據輸入參數的個數來決定。輸出參數中的第一個參數是一個JSON文本,後面的參數是需要從JSON中解析的Key。傳回值中的第一個傳回值是解析JSON過程中的出錯資訊,如果沒有出錯,則會根據輸入的Key依次輸出從JSON中解析出來的內容。使用樣本如下。
-- 根據輸入參數的個數定製輸出別名個數。
SELECT my_json_tuple(json, 'a', 'b') as exceptions, a, b FROM jsons;

-- 變長部分可以一列都沒有。
SELECT my_json_tuple(json) as exceptions, a, b FROM jsons;

-- 下面這個SQL會出現執行階段錯誤,因為別名個數與實際輸出個數不符。
-- 注意編譯時間無法發現這個錯誤。
SELECT my_json_tuple(json, 'a', 'b') as exceptions, a, b, c FROM jsons;

當本文介紹的這些擴充無法滿足您的業務需求時,建議您使用UDT實現彙總函式和UDTF的功能。詳情請參見UDT概述

說明 UDAF和UDTF的Python版本樣本請參見Python 3 UDAFPython 3 UDTF讀取MaxCompute資源樣本