官网介绍
https://cwiki.apache.org/confluence/display/Hive/DeveloperGuide+UDTF
导入必要的 Hive 依赖
<dependencies>
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>3.1.2</version>
</dependency>
</dependencies>
继承 GenericUDTF 类
继承 GenericUDTF 类后,需要实现 initialize,process,close 这三个方法
initialize 方法
public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {}
主要作用有:
- 校验参数的个数
- 校验参数的类型
- 定义要炸裂出来的返回值名称和类型(可以是多个列)
获取参数个数
argOIs.getAllStructFieldRefs().size()
获取参数类型名称
argOIs.getAllStructFieldRefs().get(0).getFieldObjectInspector().getTypeName()
定义要炸开的列名为items,返回的类型是String
List<String> fieldName = new ArrayList<>();
List<ObjectInspector> fieldOIs = new ArrayList<>();
fieldName.add("items");
fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
return ObjectInspectorFactory.getStandardStructObjectInspector(fieldName, fieldOIs);
process,forwar
public void process(Object[] args) throws HiveException {}
- args 表示传入到函数的字段(可以有多个,也可以是一个)
- 可以根据需要将相应的内容通过 forward 方法输出
获取一个json数组,并将里面的字段解析输出
// 获取输入的数据
String jsonArray = args[0].toString();
// 将 string 转换为 json 数组
JSONArray actions = new JSONArray(jsonArray);
for (int i = 0; i < actions.length(); i++) {
String[] result = new String[1];
result[0] = actions.getString(i);
forward(result);
}
完整案例如下
需求:将传入的 json 数组字符串中各个部分炸裂出来,列名为 items
代码
public class ExplodeJSONArray extends GenericUDTF {
@Override
public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {
// 参数个数检验
if (argOIs.getAllStructFieldRefs().size() != 1) {
throw new UDFArgumentException("ExplodeJSONArray 只需要一个参数");
}
// 第一个参数必须为 string
if (!"string".equals(argOIs.getAllStructFieldRefs().get(0).getFieldObjectInspector().getTypeName())) {
throw new UDFArgumentException("json_array_to_struct_array的第1个参数应为string类型");
}
// 定义返回值名称和类型
List<String> fieldName = new ArrayList<>();
List<ObjectInspector> fieldOIs = new ArrayList<>();
fieldName.add("items");
fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
return ObjectInspectorFactory.getStandardStructObjectInspector(fieldName, fieldOIs);
}
@Override
public void process(Object[] args) throws HiveException {
// 获取输入的数据,假设输入只有一个参数,那么args[0]表示第一个参数
String jsonArray = args[0].toString();
// 将 string 转换为 json 数组
JSONArray actions = new JSONArray(jsonArray);
for (int i = 0; i < actions.length(); i++) {
String[] result = new String[1];
result[0] = actions.getString(i);
# 将需要的信息炸裂出去
forward(result);
}
}
@Override
public void close() throws HiveException {
}
}
创建函数
-
将打包好的 jar包上传到 HDFS 的 /user/hive/jars 路径下
-
创建永久函数并与开发好的 java class 关联
create function explode_json_array as 'com.qi.hive.udtf.ExplodeJSONArray' using jar 'hdfs://worker-13:8020/user/hive/jars/gmall_hive_udtf-1.0-SNAPSHOT.jar';
-
如果想要更新函数,只需要将 jar 包替换,重启 hive 客户端即可
总结
这是自己在学习过程中记录的 Hive UDTF 自定义函数编写过程,若有不足请多多指正。