全部产品
Search
文档中心

MaxCompute:Contoh: Menggunakan tipe data kompleks dalam UDF

更新时间:Jul 02, 2025

Topik ini menjelaskan cara menggunakan tipe data kompleks dalam fungsi yang ditentukan pengguna (UDF) Java dan Python UDF.

Deskripsi

Dalam contoh ini, sebuah UDF bernama UDF_COMPLEX_DATA dibuat.

Catatan

Contoh ini menunjukkan cara menggunakan tipe data kompleks ARRAY, MAP, dan STRUCT dalam UDF. Untuk Java UDF, nama UDF yang sama dapat digunakan untuk tipe data tersebut berdasarkan metode overloading. Untuk Python UDF, Anda harus membuat UDF bernama UDF_COMPLEX_DATA_ARRAY, UDF_COMPLEX_DATA_MAP, dan UDF_COMPLEX_DATA_STRUCT untuk menggunakan tipe data tersebut.

  • Sintaks:

    array<string> UDF_COMPLEX_DATA(array<bigint> <as>) 
    map<string, string> UDF_COMPLEX_DATA(map<string,bigint> <ms>) 
    struct<output_name:string,output_time:string> UDF_COMPLEX_DATA(<input_name:string,input_timestamp:bigint> <st>) 
  • Deskripsi:

    Mengonversi timestamp input menjadi string waktu dalam format yyyy-MM-dd HH:mm:ss. Parameter input adalah tipe data kompleks ARRAY, MAP, dan STRUCT.

  • Parameter:

    • as: Parameter ini bertipe data ARRAY<BIGINT>. Daftar timestamp ditentukan. Parameter ini wajib.

    • ms: Parameter ini bertipe data MAP<STRING, BIGINT>. Nilai setiap elemen peta adalah timestamp. Parameter ini wajib.

    • st: Parameter ini bertipe data STRUCT. Nilai dari field input_timestamp adalah timestamp.

Prosedur pengembangan dan penggunaan

1. Menulis UDF

Kode contoh UDF Java

package com.aliyun; // Tentukan nama paket.

import com.aliyun.odps.data.Struct;
import com.aliyun.odps.udf.UDF;
import com.aliyun.odps.udf.annotation.Resolve;

import java.text.SimpleDateFormat;
import java.util.*;

@Resolve("struct<input_name:string, input_timestamp:bigint>->map<string,string>")
public class ComplexDataTypeExample extends UDF{
    private static final String PATTERN = "yyyy-MM-dd HH:mm:ss";

    /**
     * Konversikan daftar timestamp menjadi daftar string waktu.
     * @param timestamps Masukkan daftar timestamp.
     * @return Dapatkan daftar string waktu.
     */
    public List<String> evaluate(List<Long> timestamps) {
        if (timestamps == null) {
            return null;
        }
        List<String> result = new ArrayList<>();
        SimpleDateFormat formatter = new SimpleDateFormat(PATTERN);
        for (Long timestamp : timestamps) {
            Date date = new Date(timestamp < 9999999999L ? timestamp * 1000 : timestamp);
            String dateString = formatter.format(date);
            result.add(dateString);
        }
        return result;
    }

    /**
     * Konversikan timestamp tipe data MAP menjadi string waktu tipe data MAP.
     * @param timestamps Masukkan data tipe data MAP di mana nilainya adalah timestamp.
     * @return Dapatkan daftar string waktu tipe data MAP.
     */
    public Map<String, String> evaluate(Map<String, Long> timestamps) {
        if (timestamps == null) {
            return null;
        }
        Map<String, String> result = new HashMap<>(timestamps.size());
        SimpleDateFormat formatter = new SimpleDateFormat(PATTERN);
        for (String key : timestamps.keySet()) {
            Long timestamp = timestamps.get(key);
            Date date = new Date(timestamp < 9999999999L ? timestamp * 1000 : timestamp);
            String dateString = formatter.format(date);
            result.put(key, dateString);
        }
        return result;
    }

    /**
     * Konversikan timestamp menjadi string waktu.
     * @param input Masukkan timestamp tipe data STRUCT.
     * @return Dapatkan string waktu tipe data STRUCT.
     */
    public Map<String, String> evaluate(Struct input) {
        if (input == null) {
            return null;
        }
        SimpleDateFormat formatter = new SimpleDateFormat(PATTERN);
        String nameValue = (String) input.getFieldValue("input_name");
        Long timestampValue = (Long) input.getFieldValue("input_timestamp");
        Date date = new Date(timestampValue < 9999999999L ? timestampValue * 1000 : timestampValue);
        String dateString = formatter.format(date);
        Map<String, String> result = new HashMap<>(8);
        result.put("output_name", nameValue);
        result.put("output_time", dateString);
        return result;
    }
}

Dependensi berikut perlu diperkenalkan ke pom.xml:

<dependency>
  <groupId>com.aliyun.odps</groupId>
  <artifactId>odps-sdk-udf</artifactId>
  <version>0.29.10-public</version>
</dependency>

Dalam kode contoh, tiga metode evaluate didefinisikan untuk overloading UDF.

  • Metode 1: Gunakan ARRAY sebagai parameter yang sesuai dengan kelas java.util.List.

  • Metode 2: Gunakan MAP sebagai parameter yang sesuai dengan kelas java.util.Map.

  • Metode 3: Gunakan STRUCT sebagai parameter yang sesuai dengan kelas com.aliyun.odps.data.Struct.

    Catatan

    Anda tidak dapat menggunakan fitur refleksi untuk kelas com.aliyun.odps.data.Struct untuk mendapatkan nama dan tipe data bidang. Jika Anda ingin menggunakan tipe data STRUCT untuk UDF, Anda harus menambahkan @Resolve annotation ke kelas com.aliyun.odps.data.Struct. Anotasi ini hanya memengaruhi overloading UDF yang parameter input atau nilai baliknya mengandung kelas com.aliyun.odps.data.Struct.

Jika Anda menulis UDF dalam Java, Anda harus mewarisi kelas UDF. Dalam contoh ini, metode evaluate mendefinisikan tiga parameter input dari tipe LIST, MAP, dan STRUCT, yang secara terpisah mengembalikan nilai dari tipe LIST, MAP, dan MAP. Tipe data parameter input dan nilai balik digunakan sebagai tanda tangan UDF dalam pernyataan SQL. Untuk informasi lebih lanjut tentang spesifikasi dan persyaratan kode lainnya, lihat Java UDFs.

Kode contoh UDF Python 3

  • Dalam contoh berikut, parameter input bertipe data MAP<STRING, BIGINT>. Kode contoh menciptakan UDF bernama UDF_COMPLEX_DATA_MAP.

    from odps.udf import annotate
    import datetime
    @annotate('map<string,bigint>->map<string,datetime>')
    class MapExample:
        def evaluate(self, input_dict):
            output_dict = dict()
            for key in input_dict:
                value = input_dict[key]
                t = datetime.datetime.fromtimestamp(value)
                output_dict[key] = t
            return output_dict
  • Dalam contoh berikut, parameter input bertipe data ARRAY<BIGINT>. Kode contoh menciptakan UDF bernama UDF_COMPLEX_DATA_ARRAY.

    from odps.udf import annotate
    import datetime
    @annotate('array<bigint>->array<datetime>')
    class ArrayExample:
        def evaluate(self, input_list):
            output_list = list()
            for item in input_list:
                t = datetime.datetime.fromtimestamp(item)
                output_list.append(t)
            return output_list
  • Dalam contoh berikut, parameter input bertipe data STRUCT<input_name:string,input_timestamp:bigint>. Kode contoh menciptakan UDF bernama UDF_COMPLEX_DATA_STRUCT.

    from odps.udf import annotate
    import datetime, collections
    @annotate('struct<input_name:string,input_timestamp:bigint>->struct<output_name:string,output_time:datetime>')
    class StructExample:
        def evaluate(self, input_namedtuple):
            OutputNamedTuple = collections.namedtuple('output_namedtuple', ['output_name', 'output_time'])
            name_val = input_namedtuple.input_name
            time_val = datetime.datetime.fromtimestamp(input_namedtuple.input_timestamp)
            output_namedtuple = OutputNamedTuple(name_val, time_val)
            return output_namedtuple

Secara default, Python 2 digunakan untuk menjalankan UDF dalam proyek MaxCompute. Jika Anda ingin menjalankan UDF dalam Python 3, jalankan perintah berikut pada tingkat sesi: set odps.sql.python.version=cp37. Untuk informasi lebih lanjut tentang spesifikasi Python 3 UDF, lihat Python 3 UDFs.

2. Unggah sumber daya dan buat UDF

Setelah Anda mengembangkan dan men-debug kode UDF, unggah sumber daya ke MaxCompute dan buat UDF. Dalam contoh ini, sebuah Java UDF bernama UDF_COMPLEX_DATA dibuat. Untuk Python UDF, Anda harus membuat UDF berikut: UDF_COMPLEX_DATA_ARRAY, UDF_COMPLEX_DATA_MAP, dan UDF_COMPLEX_DATA_STRUCT. Untuk informasi lebih lanjut tentang cara mengunggah sumber daya dan membuat Java UDF, lihat Kemas Program Java, Unggah Paket, dan Buat MaxCompute UDF. Untuk informasi lebih lanjut tentang cara mengunggah sumber daya dan membuat Python UDF, lihat Unggah Program Python dan Buat MaxCompute UDF.

3. Gunakan UDF

  • Jalankan perintah berikut untuk mengonversi timestamp tipe data ARRAY menjadi string waktu:

    -- Panggil Java UDF.
    SELECT UDF_COMPLEX_DATA(array(1554047999, 1554047989)); 
    
    -- Panggil Python UDF.
    set odps.sql.python.version=cp37; -- Untuk menggunakan Python3 UDF, jalankan perintah ini untuk mengaktifkan Python3.
    SELECT UDF_COMPLEX_DATA_ARRAY(array(1554047999, 1554047989)); 

    Hasil berikut dikembalikan:

    +---------------------------------------------+
    | _c0                                         |
    +---------------------------------------------+
    | [2019-03-31 23:59:59, 2019-03-31 23:59:49]  |
    +---------------------------------------------+
  • Jalankan perintah berikut untuk mengonversi timestamp tipe data MAP menjadi string waktu:

    -- Panggil Java UDF.
    SELECT UDF_COMPLEX_DATA(map('date1', 1554047989, 'date2', 1554047999));
    
    -- Panggil Python UDF.
    set odps.sql.python.version=cp37; -- Untuk menggunakan Python3 UDF, jalankan perintah ini untuk mengaktifkan Python3.
    SELECT UDF_COMPLEX_DATA_MAP(map('date1', 1554047989, 'date2', 1554047999)); 

    Hasil berikut dikembalikan:

    +----------------------------------------------------------------+
    | _c0                                                            |
    +----------------------------------------------------------------+
    | {"date1":"2019-03-31 23:59:49","date2":"2019-03-31 23:59:59"}  |
    +----------------------------------------------------------------+
  • Jalankan perintah berikut untuk mengonversi timestamp tipe data STRUCT menjadi string waktu:

    -- Panggil Java UDF.
    SELECT UDF_COMPLEX_DATA(struct('date', 1554047989)); 
    
    -- Panggil Python UDF.
    set odps.sql.python.version=cp37; -- Untuk menggunakan Python3 UDF, jalankan perintah ini untuk mengaktifkan Python3.
    SELECT UDF_COMPLEX_DATA_STRUCT(struct('date', 1554047989)); 

    Hasil berikut dikembalikan:

    +-------------------------------------------------------------+
    | _c0                                                         |
    +-------------------------------------------------------------+
    | {"output_name":"date","output_time":"2019-03-31 23:59:49"}  |
    +-------------------------------------------------------------+