簡體   English   中英

Apache Spark SQL StructType 和 UDF

[英]Apache Spark SQL StructType together with UDF

Spark 1.6 / Java-7

初始 dataframe 帶新列

# adding new column for the UDF computation:
df = df.withColumn("TEMP_COLUMN", lit(null));

UDF function 創建新的 StructType 並將其放入單元格的正確格式是什么?

public static DataFrame compute(SQLContext sqlContext, DataFrame df) {
    sqlContext.udf().register("compute", new MyUdf(), new ArrayType(new StructType(), true));
    return df.withColumn("TEMP_COLUMN", functions.callUDF("compute"));
}

class MyUdf implements UDF0<List<StructType>> {
@Override
public  List<StructType> call() {
    ...
    return ? // what must be returned here? List<StructType> or List<String> or anything else?
}


+-------------------------+
|TEMP_COLUMN              |
+-------------------------+
|[A[1, 2, 3], B[4, 5, 6]] |
+-------------------------+

我想要一個包含元素數組的結構,每個元素都有幾個字段。
我不明白,注冊類型new ArrayType(new StructType(), true)是否正確,UDF function List<StructType>的返回類型是否相同。
數據應該如何返回? 是不是像new StructType(new StructField[]{new StructField(...))

回答我自己的問題,因為我們很幸運地找到了如何做到這一點:

假設我們有一個“復雜”的結構來滿足我們的需求:

MapType CLIENTS_INFO_DATA_TYPE = DataTypes.createMapType(
  DataTypes.StringType,
  DataTypes.createStructType(
    new StructField[] {
        DataTypes.createStructField("NAME_1", DataTypes.DoubleType, false),
        DataTypes.createStructField("NAME_2", DataTypes.DoubleType, false),
        DataTypes.createStructField("NAME_3", DataTypes.DoubleType, false)
  ),
  true
);


StructType COMPLEX_DATA_TYPE = DataTypes.createStructType(new StructField[] {
  DataTypes.createStructField("CLIENTS_INFO", CLIENTS_INFO_DATA_TYPE, true),
  DataTypes.createStructField("COMMENT", DataTypes.StringType, true)
}

它的架構:

dataFrame.printSchema()

|-- COMPLEX_DATA_TYPE: struct (nullable = true)
|    |-- CLIENTS_INFO: map (nullable = true)
|    |    |-- key: string
|    |    |-- value: struct (valueContainsNull = true)
|    |    |    |-- NAME_1: double (nullable = false)
|    |    |    |-- NAME_2: double (nullable = false)
|    |    |    |-- NAME_3: double (nullable = false)
|    |-- COMMENT: string (nullable = true)

接下來,我們必須注冊使用我們的結構運行的 UDF function:

DataFrame compute(SQLContext sqlContext, DataFrame df) {
sqlContext.udf().register(
        "computeUDF",
        new MyUDF(),
        COMPLEX_DATA_TYPE);

  return df.withColumn("TEMP_FIELD_NAME", functions.callUDF("computeUDF", field_1.getColumn(), field_2.getColumn()));
}

最后一步是 UDF function 本身返回一個Row object (將轉換為我們的結構):

public final class MyUDF implements UDF2<Double, Double, Row> {
@Override
public Row call(Double value1, Double value2) {
    Map<String, Row> clientsInfoMap = new HashMap<>();
    ...
    for (Map.Entry<String, ClientInfo> clientInfoEntry : clientsInfo.entrySet()) {
        final String client = clientInfoEntry.getKey();
        final ClientInfo clientInfo = clientInfoEntry.getValue();

        final Double[] clientInfoValues = {10.0, 20.0, 30.0};
        
        Row clientInfoRow = new GenericRow(clientInfoValues);
        clientsInfoMap.put(client, clientInfoRow);
    }

    Object[] fullClientsInfo = new Object[] {clientsInfoMap, "string-as-a-comment"};
    return new GenericRow(fullClientsInfo);
  }
}

現在,由於它是一個結構,我們可以使用TEMP_FIELD_NAME.CLIENTS_INFO和其他任何名稱來 select。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM