Topik ini menjelaskan cara menggunakan fungsi yang ditentukan pengguna (UDF) Java atau UDF Python untuk mendapatkan nilai kunci tertentu dalam string pasangan kunci-nilai tanpa pemisah.
Deskripsi
Dalam contoh ini, UDF bernama UDF_EXTRACT_KEY_VALUE dibuat.
Sintaks:
STRING UDF_EXTRACT_KEY_VALUE(STRING <s>, STRING <split1>, STRING <split2>, STRING <keyname>)
Deskripsi:
Menggunakan split1 untuk membagi string s menjadi pasangan kunci-nilai, menggunakan split2 untuk membagi pasangan kunci-nilai menjadi kunci dan nilai, lalu mendapatkan nilai dari kunci yang ditentukan oleh keyname.
CatatanUDF ini tidak cocok untuk string dengan pemisah. Untuk informasi lebih lanjut tentang cara mendapatkan nilai kunci tertentu dalam string yang memiliki pemisah, lihat Contoh: Mendapatkan Nilai dari String dengan Pemisah.
Parameter:
s: String sumber. Nilai parameter ini bertipe data STRING. Parameter ini wajib.
split1: Pemisah string yang digunakan untuk mendapatkan pasangan kunci-nilai. Nilai parameter ini bertipe data STRING. Parameter ini wajib.
split2: Pemisah kunci-nilai yang digunakan untuk mendapatkan kunci dan nilai. Nilai parameter ini bertipe data STRING. Parameter ini wajib.
keyname: Kunci yang nilainya ingin didapatkan. Nilai parameter ini bertipe data STRING. Parameter ini wajib.
Prosedur
1. Menulis UDF
Kode contoh UDF Java
package com.aliyun.rewrite; // Tentukan nama paket.
import com.aliyun.odps.udf.UDF;
import java.util.HashMap;
import java.util.Map;
public class ExtractKeyValue extends UDF{
private static final int KEY_VALUE_LENGTH = 2;
/**
* Gunakan split1 untuk membagi string menjadi pasangan kunci-nilai. Lalu, gunakan split2 untuk membagi pasangan kunci-nilai menjadi kunci dan nilai.
* @param str String sumber.
* @param split1 Pemisah yang digunakan untuk membagi string menjadi pasangan kunci-nilai.
* @param split2 Pemisah yang digunakan untuk membagi pasangan kunci-nilai menjadi kunci dan nilai.
* @param keyname Nama kunci yang nilainya ingin Anda dapatkan.
* @return Nilai hasil.
*/
public String evaluate(String str, String split1, String split2, String keyname) {
try {
// Gunakan split1 untuk membagi string menjadi pasangan kunci-nilai.
if (str == null || "".equals(str)) {
return null;
}
Map<String, String> keyValueCache = new HashMap<>(8);
String[] extractedKeyValues = str.split(split1);
// Gunakan split2 untuk membagi pasangan kunci-nilai yang diperoleh menjadi kunci dan nilai.
for (String keyValue : extractedKeyValues) {
storeKeyValue(keyValueCache, keyValue, split2);
}
// Dapatkan nilai dari kunci yang ditentukan.
return keyValueCache.get(keyname);
} catch (Exception e) {
return null;
}
}
/**
* Gunakan parameter split untuk membagi pasangan kunci-nilai. Lalu, cache hasil yang diperoleh di keyValueCache.
*
* @param keyValueCache Pasangan kunci-nilai yang di-cache setelah pembagian.
* @param keyValue Pasangan kunci-nilai yang ingin Anda bagi.
* @param split Pemisah.
*/
private void storeKeyValue(Map<String, String> keyValueCache, String keyValue, String split) {
if (keyValue == null || "".equals(keyValue)) {
return;
}
String[] keyValueArr = keyValue.split(split);
if (keyValueArr.length == KEY_VALUE_LENGTH) {
keyValueCache.put(keyValueArr[0], keyValueArr[1]);
}
}
}Jika Anda menulis UDF dalam Java, Anda harus mewarisi kelas UDF. Dalam contoh ini, metode evaluate mendefinisikan empat parameter input dengan tipe data STRING dan nilai balikan dengan tipe data STRING. Tipe data parameter input dan nilai balikan digunakan sebagai tanda tangan UDF dalam pernyataan SQL. Untuk informasi tentang spesifikasi dan persyaratan kode lainnya, lihat UDF Java.
Kode contoh UDF Python 3
from odps.udf import annotate
@annotate("string,string,string,string->string")
class ExtractKeyValue(object):
def evaluate(self, s, split1, split2, keyname):
if not s:
return None
# Gunakan split1 untuk membagi string menjadi pasangan kunci-nilai, dan gunakan split2 untuk membagi pasangan kunci-nilai menjadi kunci dan nilai.
key_value_cache = dict(kv.split(split2) for kv in s.split(split1) if kv)
# Dapatkan nilai dari kunci yang ditentukan.
return key_value_cache.get(keyname)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 UDF Python 3, lihat UDF Python 3.
Kode contoh UDF Python 2
#coding:utf-8
from odps.udf import annotate
@annotate("string,string,string,string->string")
class ExtractKeyValue(object):
def evaluate(self, s, split1, split2, keyname):
if not s:
return None
# Gunakan split1 untuk membagi string menjadi pasangan kunci-nilai, dan gunakan split2 untuk membagi pasangan kunci-nilai menjadi kunci dan nilai.
key_value_cache = dict(kv.split(split2) for kv in s.split(split1) if kv)
# Dapatkan nilai dari kunci yang ditentukan.
return key_value_cache.get(keyname)Jika karakter Cina muncul dalam kode UDF yang ditulis dalam Python 2, kesalahan akan dikembalikan saat Anda menjalankan UDF. Untuk mengatasi masalah ini, tambahkan deklarasi encoding ke header kode. Format deklarasinya adalah #coding:utf-8 atau # -*- coding: utf-8 -*-. Kedua format tersebut setara. Untuk informasi lebih lanjut tentang spesifikasi UDF Python 2, lihat UDF Python 2.
2. Unggah sumber daya dan buat UDF
Setelah mengembangkan dan men-debug kode UDF, unggah sumber daya ke MaxCompute dan buat UDF. Dalam contoh ini, UDF bernama UDF_EXTRACT_KEY_VALUE dibuat. Untuk informasi lebih lanjut tentang cara mengunggah sumber daya dan membuat UDF Java, lihat Kemas Program Java, Unggah Paket, dan Buat UDF MaxCompute. Untuk informasi lebih lanjut tentang cara mengunggah sumber daya dan membuat UDF Python, lihat Unggah Program Python dan Buat UDF MaxCompute.
3. Gunakan UDF
Setelah UDF dibuat, jalankan perintah berikut untuk mendapatkan nilai dari kunci name dalam string pasangan kunci-nilai:
set odps.sql.python.version=cp37; -- Untuk menggunakan UDF dalam Python 3, jalankan perintah ini.
SELECT UDF_EXTRACT_KEY_VALUE('name:zhangsan;age:21;',';',':','name');Hasil berikut dikembalikan:
+----------+
| _c0 |
+----------+
| zhangsan |
+----------+