hive-UDTF的编写

如何编写一个udf请参考上一篇文章:
hive自定义UDF函数遇到的坑

下面是具体的UDTD的建立:
package com.udf.test;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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 org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;

import java.util.List;

public class UdtfTest extends GenericUDTF {

static final Log log = LogFactory.getLog(UdtfTest.class.getName());

/**
 * 其中initialize方法和UDF中类似,主要是判断输入类型并确定返回的字段类型
 **/
@Override
public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {
    List<String> colName = Lists.newLinkedList();
    colName.add("item_id");
    colName.add("item_name");
    colName.add("group");
    colName.add("item_detail");
    List<ObjectInspector> resType = Lists.newLinkedList();
    resType.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
    resType.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
    resType.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
    resType.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
    // 返回分别为列名 和 列类型
    return ObjectInspectorFactory.getStandardStructObjectInspector(colName, resType);
}

/**
 * process方法对udft函数输入的每一样进行操作,通过调用forward方法返回一行或多行数据
 */
@Override
public void process(Object[] args) throws HiveException {
    if (args[0] == null) {
        return;
    }
    log.info("入参信息="+args.toString());
    String[] strArr = new String[4];
    String strings = args[0].toString();
    log.info("需要转换数组的参数="+strings);   
    // 引入了阿里巴巴的json框架,导入自己的jar就可以了
    JSONArray jsonArray = JSONArray.parseArray(strings);
    for (int i = 0; i < jsonArray.size(); i++) {
        Object oneObj = jsonArray.get(i);
        if (null == oneObj) {
            continue;
        } else {
            JSONObject jsonObject = JSONObject.parseObject(oneObj.toString());
            strArr[0]= String.valueOf(jsonObject.get("item_id"));
            strArr[1]= String.valueOf(jsonObject.get("item_name"));
            strArr[2]= String.valueOf(jsonObject.get("group"));
            strArr[3]= String.valueOf(jsonObject.get("item_detail"));
            forward(strArr);
        }
    }
}

/**
 * close方法在process调用结束后调用,用于进行其它一些额外操作,只执行一次。
 */
@Override
public void close() throws HiveException {

}

}

此函数生成后怎么使用:
select a.pid,a.service_code,b.e,b.f,b.e,b.g from ods.tpdg_service_call_info a lateral view udtf_test(get_json_object(a.result_data, ‘$.risk_items’)) b as e,f,e,g
where a.id=6615;
注意点: 1、as e,f,e,g 这里的个数必须与 initialize设置的个数一致
2、返回的类容key和value不能有重复的,因为lateral view 对字段做了分组处理,如果相同的值,相同的key就会报错

这种类似的功能还可以根据explode函数实现,但是此函数有个缺陷,只能读取数组的字段或者通过split函数生成的数组,太复杂的json格式就不能识别了。

select explode(split(regexp_replace(get_json_object(result_data, ‘$.risk_items’),’\[|\]’,’’),’\},\{’)) from ods.tpdg_service_call_info where id=6615;
这句sql只能解析这种单层的数据: [{“name”:“zhangsan”},{“name”:“lisi”}]

UDTF和UDF是Hive中的两种不同类型的函数。 UDTF(User-Defined Table-Generating Function)是用户自定义的表生成函数,用于在查询中生成表。UDTF函数在SELECT子句中使用,可以将一列或多列的输入数据转换为多个输出列,并生成一个新的表。UDTF函数通常用于将一列的值拆分成多个行,以实现行转列的效果。在Hive中,使用lateral view关键字来调用UDTF函数。\[1\] UDF(User-Defined Function)是用户自定义的函数,用于在查询中对数据进行转换和处理。UDF函数可以接受一个或多个输入参数,并返回一个值作为输出。UDF函数通常用于对单个数据项进行计算或转换。编写UDF函数需要继承两个类:org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver和org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator。\[2\] 举个例子,如果需要将一列的值拆分成多个行,可以使用UDTF函数。例如,使用lateral view和split_udtf函数可以实现行转列的效果: ``` select id, names, score from udtf_test lateral view split_udtf(name,',') temp as names; ``` 另外,如果只需要对单个数据项进行计算或转换,可以使用UDF函数。例如,使用add_udf函数可以将score列的值加上10: ``` select id, name, score, add_udf(score) as add_score from udf_test; ``` 总结来说,UDTF函数用于生成表,通常用于行转列的操作;而UDF函数用于对单个数据项进行计算或转换。 #### 引用[.reference_title] - *1* *3* [Hive中UDF、UDTF 、UDAF函数详解及示例](https://blog.csdn.net/qq_40579464/article/details/105903405)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [hive udf,udaf和udtf](https://blog.csdn.net/whdxkcx/article/details/107171065)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值