HIVE自定义UDTF函数

Posted 牧码文

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HIVE自定义UDTF函数相关的知识,希望对你有一定的参考价值。

UDTF函数

文章目录

HIVE提供了丰富的内置函数,但是对于一些复杂逻辑还是需要自定义函数来实现,对此,HIVE也提供了一些自定义的接口和类。
UDF:一进一出,一对一的关系数据
UDTF:一进多处,一对多的关系数据
UDAF:多进一出,多对一的关系数据

一、继承GenericUDTF类

实现三个方法:

initialize方法

两个作用:

  1. 初始化参数,判断参数类型是否符合要求

  2. 设置输出列和类型

    ArrayList<String> fieldNames = new ArrayList<String>();
    ArrayList<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();
    
    fieldNames.add("col1");  // 列名为col1
    fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);  // 类型String
    fieldNames.add("col2");
    fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
    

process方法

处理数据,通过forward方法将数据写出,没写出一次,代表为一行,可以传入一个数组

forward(result);

close方法

顾名思义,打扫干净,下一位

二、源码解析

因为在之前的版本UDTF的initialize方法提供的是:

@Override
public StructObjectInspector initialize(ObjectInspector[] argOIs) throws UDFArgumentException 
  return super.initialize(argOIs);

现在上述的方式已经不推荐了,改作了:

@Override
public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException 

return super.initialize(argOIs);

将一个参数数组转变为了一个结构对象检查器,这个怎么使用的?

看一下super的实现:

public StructObjectInspector initialize(StructObjectInspector argOIs)
      throws UDFArgumentException 
  List<? extends StructField> inputFields = argOIs.getAllStructFieldRefs();
  ObjectInspector[] udtfInputOIs = new ObjectInspector[inputFields.size()];
  for (int i = 0; i < inputFields.size(); i++) 
    udtfInputOIs[i] = inputFields.get(i).getFieldObjectInspector();
  
  return initialize(udtfInputOIs);

如果需要校验参数类型,通过size方法校验长度,通过getTypeName方法校验类型

//对输入参数个数进行进行检验
if (argOIs.getAllStructFieldRefs().size()!=1) 
        throw new UDFArgumentException ("args must be 1");
    
//对输入参数的类型校验
    if(!"string".equals(argOIs.getAllStructFieldRefs().get(0).getFieldObjectInspector().getTypeName().toLower()))
        throw new  UDFArgumentException("args type must be string");
     

其实就是将参数列表封装成了StructObjectInspector对象,如果想要校验参数,那么通过上述的方式,可以看到,调用getAllStructFieldRefs方法,获取所有的输入列列表,遍历就可以取到参数列表了

inputFields.get(i).getFieldObjectInspector();

process方法就是处理逻辑的方法,每次输出一个forward,就会分割为一列

String[] result = comment.split(":");
forward(result);

三、例子

按照逗号进行分割字符串,输出列

public class ExplodeArray extends GenericUDTF 
    public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException 
        //定义返回值名称
        List<String> filedNames = new ArrayList<String>();
        //校验返回值类型
        List<ObjectInspector> filedOIs= new ArrayList<ObjectInspector>();
        filedNames.add("col1");
           filedOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
        return  ObjectInspectorFactory.getStandardStructObjectInspector(filedNames,filedOIs);
    

    public void process(Object[] objects) throws HiveException 
        String comment= objects[0].toString();
        String[] str = comment.split(",");
		for(String s : str)
		    forward(s);
		
    

    public void close() throws HiveException 

    

注意在UDTF函数中,会出现传入数据异常的问题,在这里我并没有校验参数,在实际生产中是需要校验参数的。

以上是关于HIVE自定义UDTF函数的主要内容,如果未能解决你的问题,请参考以下文章

Hive--10---函数----自定义函数 (UDF-UDAF-UDTF)

Hadoop3集群搭建之——hive添加自定义函数UDTF (一行输入,多行输出)

hive自定义函数UDF UDTF UDAF

Hive 自定义函数 UDF UDAF UDTF

Hive自定义函数UDF和UDTF

Hadoop3集群搭建之——hive添加自定义函数UDTF