hive自定义函数
一、自定义UDF函数
0、需求:
自定义一个 UDF 实现计算给定字符串的长度,例如:
hive(default)> select my_len("abcd");
4
1、创建一个Maven工程
导入依赖:
<dependencies>
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>3.1.2</version>
</dependency>
</dependencies>
2、创建一个类
package com.smxy.hive;
/*
* @Author Jiang Yijia
* @Date 2021/5/11
*
* @Description:
*
*/
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
/**
* 自定义 UDF 函数,需要继承 GenericUDF 类
* 需求: 计算指定字符串的长度
*/
public class MyUDF extends GenericUDF {
/**
*
*@param objectInspectors 输入参数类型的鉴别器对象
* @return 返回值类型的鉴别器对象
*@throws UDFArgumentException
* @Description: 校验数据参数个数
*/
@Override
public ObjectInspector initialize(ObjectInspector[] objectInspectors) throws UDFArgumentException {
// 判断输入参数的个数
if(objectInspectors.length !=1){
throw new UDFArgumentLengthException("参数个数不为1");
}
// 判断输入参数的类型
if(!objectInspectors[0].getCategory().equals(ObjectInspector.Category.PRIMITIVE)){
throw new UDFArgumentTypeException(0,"输入参数类型错误!");
}
//函数本身返回值为 int,需要返回 int 类型的鉴别器对象
return PrimitiveObjectInspectorFactory.javaIntObjectInspector;
}
/**
* 函数的逻辑处理
*@param deferredObjects 输入的参数
*@return 返回值
*@throws HiveException
* @Description: 处理数据
*/
@Override
public Object evaluate(DeferredObject[] deferredObjects) throws HiveException {
if(deferredObjects[0].get().toString() == null){
return 0;
}
// 返回输入参数长度
return deferredObjects[0].get().toString().length();
}
@Override
public String getDisplayString(String[] strings) {
return "";
}
}
3、打成jar包上传到服务器/opt/module/data/hive-demo-1.0-SNAPSHOT.jar
4、创建临时函数与开发好的 java class 关联
hive (default)> create temporary function my_len as "com.smxy.hive.MyUDF";
my_len:自定义函数名
5、运行结果:
hive (test)> select my_len(name) from student;
OK
_c0
6
4
8
4
6
6
6
二、自定义UDTF函数
1、创建一个类
package com.smxy.hive;
/*
* @Author Jiang Yijia
* @Date 2021/5/12
*
* @Description:
*
*/
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import java.util.ArrayList;
import java.util.List;
/*
* 输入数据:holle,world,hive
* 输出:
* holle
* world
* hive
*/
public class MyUDTF extends GenericUDTF {
// 输出数据的集合
private ArrayList<String> outList = new ArrayList<>();
@Override
public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {
// 输出数据的默认列名,可以被别名覆盖
List<String> fieldNames = new ArrayList<>();
fieldNames.add("word");
// 输出数据的类型
List<ObjectInspector> fieldOIs = new ArrayList<>();
return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs);
}
// 处理输入数据
@Override
public void process(Object[] objects) throws HiveException {
//1.获取输入数据
String arg = objects[0].toString();
//2.获取数据传入的第二个参数,此处为分隔符
String splitKey = objects[1].toString();
//3.将原始数据按照传入的分隔符进行切分
String[] fields = arg.split(splitKey);
//4.遍历切分后的结果,并写出
for (String field : fields) {
//集合为复用的,首先清空集合
outList.clear();
//将每一个单词添加至集合
outList.add(field);
//将集合内容写出
forward(outList);
}
}
// 收尾方法
@Override
public void close() throws HiveException {
}
}
其余步骤与上边相同
2、打成jar包上传到服务器/opt/module/data/hive-demo-1.0-SNAPSHOT.jar
3、创建临时函数与开发好的 java class 关联
hive (default)> create temporary function my_udtf as "com.smxy.hive.MyUDTF";
4、使用函数
hive (default)> select my_udtf("hello,world,hadoop,hive",",");