Hive UDF GDF UDTF编写与实现
hive 自定义函数实现
UDF | GDF | UDTF 区别
- UDF:一进一出(hive3 已经废除)
- GDF:一进一出(hive3 支持的GDF)
- UDTF:一进多出
业务前景
测试数据为:字符串(JSON数组格式 [{},{},{}] )
[{\"title\": \"转让背书\", \"endorseName\": \"山东泰山钢铁集团有限公司\", \"endorseeName\": \"山东汶汇港物流有限公司\", \"isTransfer\": \"可以转让\", \"endorseDate\": \"2021-06-10\"}, {\"title\": \"转让背书\", \"endorseName\": \"山东汶汇港物流有限公司\", \"endorseeName\": \"山东泰通达物流有限公司\", \"isTransfer\": \"可以转让\", \"endorseDate\": \"2021-06-11\"}]
通过hive自定义函数将json数组中的 endorseName和endorseeName取出后并去重输出,或者将二者取出后在hive中进行去重操作
输出格式:
-- UDF GDF输出格式:
山东泰山钢铁集团有限公司,山东汶汇港物流有限公司,山东汶汇港物流有限公司,山东泰通达物流有限公司
-- UDTF 输出格式
山东泰山钢铁集团有限公司
山东汶汇港物流有限公司
山东汶汇港物流有限公司
山东泰通达物流有限公司
实现思路:
- 将字符串转换为JSON数组进行处理
- 将字符串转换为对象集合的方式获取数据格式
前期准备
- 使用IDEA创建Maven项目
- 导入相应依赖包
- 创建相应的package并创建相应JAVA类
- 所有代码编写完成后将项目进行打包处理
创建项目
我的创建项目已经目录截图如下,以下格式仅供参考,需根据自己的需求进行整理:
导入maven
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>domain_endorse</artifactId><version>1.0-SNAPSHOT</version><!-- 定义hive项目版本信息 --><properties><project.build.sourceEncoding>UTF8</project.build.sourceEncoding><hive.version>3.1.2</hive.version></properties><dependencies><!--添加hive依赖--><dependency><groupId>org.apache.hive</groupId><artifactId>hive-exec</artifactId><version>${hive.version}</version></dependency><!-- 字符串转对象集合的时候才导此包--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version></dependency><!-- 注解 @Data 使用的依赖--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.10</version></dependency></dependencies><!-- 项目打jar包时使用 --><build><plugins><plugin><artifactId>maven-compiler-plugin</artifactId><version>2.3.2</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><artifactId>maven-assembly-plugin</artifactId><configuration><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs></configuration><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin></plugins></build>
</project>
UDF函数实现
将字符串转换为集合对象来实现
package com.sddw.udf;import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.json.JSONException;import java.util.*;public class EndorseUDF extends UDF {// 对象集合@Datapublic static class EndorseObj{private String endorseName;private String endorseeName;}public String evaluate(String line) {// 定义set集合,接收背书企业信息,(去重)Set set = new HashSet<String>();// 处理脏数据if (line == null || line == "") {return null;}// 判断数据的完整性,不完整数据剔除if (line.trim().startsWith("[{") && line.trim().endsWith("}]")) {try {// 将数据转换为对象集合List<EndorseObj> list = JSONObject.parseArray(line, EndorseObj.class);for (int i = 0; i < list.size(); i++) {set.add(list.get(i).endorseeName);set.add(list.get(i).endorseName);}/*String[] lines = line.replace("\"","").split(",");for (int i = 0 ;i < lines.length;i++){if (lines[i].contains("endorseeName") || lines[i].contains("endorseName")) {String[] name = lines[i].split(":");set.add(name[1]);}}*/} catch (JSONException e) {e.printStackTrace();}} else {// 剔除不完整数据return null;}// 将set集合准换为字符串String endorsename = String.join(",", set);return endorsename;}public static void main(String[] args) {String line = "[{\"title\": \"转让背书\", \"endorseName\": \"山东泰山钢铁集团有限公司\", \"endorseeName\": \"山东汶汇港物流有限公司\", \"isTransfer\": \"可以转让\", \"endorseDate\": \"2021-06-10\"}, {\"title\": \"转让背书\", \"endorseName\": \"山东汶汇港物流有限公司\", \"endorseeName\": \"山东泰通达物流有限公司\", \"isTransfer\": \"可以转让\", \"endorseDate\": \"2021-06-11\"}, {\"title\": \"转让背书\", \"endorseName\": \"山东泰通达物流有限公司\", \"endorseeName\": \"山东维利达经贸有限公司\", \"isTransfer\": \"可以转让\", \"endorseDate\": \"2021-06-11\"}, {\"title\": \"转让背书\", \"endorseName\": \"山东维利达经贸有限公司\", \"endorseeName\": \"莱芜市合盛铸造材料经营部\", \"isTransfer\": \"可以转让\", \"endorseDate\": \"2021-06-11\"}, {\"title\": \"转让背书\", \"endorseName\": \"莱芜市合盛铸造材料经营部\", \"endorseeName\": \"山东六六六贸易有限公司\", \"isTransfer\": \"可以转让\", \"endorseDate\": \"2021-06-11\"}, {\"title\": \"转让背书\", \"endorseName\": \"山东六六六贸易有限公司\", \"endorseeName\": \"山东禾壮信息技术有限公司\", \"isTransfer\": \"可以转让\", \"endorseDate\": \"2021-06-21\"}, {\"title\": \"转让背书\", \"endorseName\": \"山东禾壮信息技术有限公司\", \"endorseeName\": \"山东纳凯建材有限公司\", \"isTransfer\": \"可以转让\", \"endorseDate\": \"2021-06-21\"}, {\"title\": \"转让背书\", \"endorseName\": \"山东纳凯建材有限公司\", \"endorseeName\": \"聊城信源集团有限公司\", \"isTransfer\": \"可以转让\", \"endorseDate\": \"2021-06-21\"}, {\"title\": \"转让背书\", \"endorseName\": \"聊城信源集团有限公司\", \"endorseeName\": \"苏州弗兰特环保科技有限公司\", \"isTransfer\": \"可以转让\", \"endorseDate\": \"2021-06-22\"}, {\"title\": \"转让背书\", \"endorseName\": \"苏州弗兰特环保科技有限公司\", \"endorseeName\": \"潍坊祥盛控制设备科技有限公司\", \"isTransfer\": \"可以转让\", \"endorseDate\": \"2021-06-30\"}, {\"title\": \"转让背书\", \"endorseName\": \"潍坊祥盛控制设备科技有限公司\", \"endorseeName\": \"德州陵城区陆达商贸有限公司\", \"isTransfer\": \"可以转让\", \"endorseDate\": \"2021-06-30\"}]";String x = new EndorseUDF().evaluate(line);System.out.println(x);}
}
GDF实现
将字符串转换为集合对象来实现
package com.sddw.gdf;import com.alibaba.fastjson.JSONObject;
import lombok.Data;
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;
import org.json.JSONException;import java.util.*;/*** 设置GDF实现将Json中的背书企业,背背书企业名称进行字符串输出*/
public class EndorseGDF extends GenericUDF {@Datapublic static class EndorseObj{private String endorseName;private String endorseeName;}/**** @param objectInspectors 输入参数类型的鉴别器对象* @return 返回值* @throws UDFArgumentException*/@Overridepublic ObjectInspector initialize(ObjectInspector[] objectInspectors) throws UDFArgumentException {// 判断输入参数的个数if (objectInspectors.length != 1) {throw new UDFArgumentLengthException("Input Args Length Error!!!");}// 判断输入参数的类型if (!objectInspectors[0].getCategory().equals(ObjectInspector.Category.PRIMITIVE)) {throw new UDFArgumentTypeException(0, "Input Args Type Error!!!");}//函数本身返回值为string,需要返回string类型的鉴别器对象return PrimitiveObjectInspectorFactory.javaStringObjectInspector;}/**** @param deferredObjects 输入参数* @return 返回值* @throws HiveException*/@Overridepublic String evaluate(DeferredObject[] deferredObjects) throws HiveException {String line = deferredObjects[0].get().toString();// 定义set集合,接收背书企业信息,(去重)Set set = new HashSet<String>();// 处理脏数据if (line == null || line.length() == 0) {return null;}// 判断数据的完整性,不完整数据剔除if (line.trim().startsWith("[{") && line.trim().endsWith("}]")) {try {// 将数据转换为对象集合List<EndorseObj> list = JSONObject.parseArray(line, EndorseObj.class);for (int i = 0; i < list.size(); i++) {set.add(list.get(i).endorseeName);set.add(list.get(i).endorseName);}} catch (JSONException e) {e.printStackTrace();}} else {// 剔除不完整数据return null;}// 将set集合准换为字符串String endorsename = String.join(",", set);return endorsename;}@Overridepublic String getDisplayString(String[] strings) {return null;}
}
UDTF实现
通过将字符串转换为JSON数组的方式进行实现
package com.sddw.udtf;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.StructField;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.json.JSONArray;
import org.json.JSONObject;import java.util.ArrayList;
import java.util.List;public class EndorseUDTF extends GenericUDTF {/*** 初始化* @param argOIs* @return* @throws UDFArgumentException*/@Overridepublic StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {//1.获取传入的参数List<? extends StructField> inputFields = argOIs.getAllStructFieldRefs();//2.判断参数个数是否为一个?if (inputFields.size() != 1) {throw new UDFArgumentException("只需要一个参数");}//3.定义返回值名称和类型//返回的字段名List<String> fieldNames = new ArrayList<>();fieldNames.add("endorsecorp");//返回的字段类型List<ObjectInspector> fieldOIs = new ArrayList<>();fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs);}/*** 具体实现方法* @param objects* @throws HiveException*/@Overridepublic void process(Object[] objects) throws HiveException {//1.获取传入的数据String jsonArray = objects[0].toString();// 判断JSON数组的完整性,非完整的剔除if (jsonArray.startsWith("[{") && jsonArray.endsWith("}]")) {//2.将string转化为json数组JSONArray actions = new JSONArray(jsonArray);//3.循环取出json数组的元素,依次写出for (int i = 0; i < actions.length(); i++) {String[] result = new String[1];result[0] = actions.getString(i);JSONObject jsonObject = new JSONObject(result[0]);if (jsonObject.toString().contains("endorseName") && jsonObject.toString().contains("endorseeName")) {// 获取JSON中的数据String endorseName = jsonObject.getString("endorseName").replace("(", "(").replace(")", ")");String endorseeName = jsonObject.getString("endorseeName").replace("(", "(").replace(")", ")");// 将数据写入forward(endorseName);forward(endorseeName);}}}}@Overridepublic void close() throws HiveException {}
}
项目打包
项目完成并测试通过后,将项目进行打包上传到hive所在的集群中
项目打包完成后会产生两个文件,一个是含有maven,一个是不含maven依赖,如果我们只使用hive的依赖不涉及到其他的依赖建议直接上传不含maven依赖的jar包,如果涉及到其它maven依赖的,必须上传含有maven依赖的jar包
创建临时函数
add jar /opt/data/domain_endorse.jar;
create temporary function endorseudf as 'com.sddw.udf.EndorseUDF';
create temporary function endorsegdf as 'com.sddw.gdf.EndorseGDF';
create temporary function endorseudtf as 'com.sddw.udtf.EndorseUDTF';
-- 临时喊出退出shell终端后函数立马失效drop function if exists endorsegdf;
drop function if exists endorseudf;
drop function if exists endorseudf;-- 测试:
select endorseudtf('[{"title": "转让背书", "endorseName": "江苏普莱姆新材料有限公司", "endorseeName": "邯郸市邯山区润川贸易有限公司", "isTransfer": "可转让", "endorseDate": "2020-12-24"}, {"title": "转让背书", "endorseName": "邯郸市邯山区润川贸易有限公司", "endorseeName": "宁波久营贸易有限公司", "isTransfer": "可转让", "endorseDate": "2020-12-25"}, {"title": "转让背书", "endorseName": "宁波久营贸易有限公司", "endorseeName": "嵊州市恒鑫金属制管有限公司", "isTransfer": "可转让", "endorseDate": "2020-12-25"}, {"title": "转让背书", "endorseName": "嵊州市恒鑫金属制管有限公司", "endorseeName": "建龙北满特殊钢有限责任公司", "isTransfer": "可转让", "endorseDate": "2020-12-25"}, {"title": "转让背书", "endorseName": "建龙北满特殊钢有限责任公司", "endorseeName": "无锡容大环境科技有限公司", "isTransfer": "可转让", "endorseDate": "2020-12-31"}, {"title": "转让背书", "endorseName": "无锡容大环境科技有限公司", "endorseeName": "宜兴市清泰净化剂有限公司", "isTransfer": "可转让", "endorseDate": "2021-01-19"}, {"title": "转让背书", "endorseName": "宜兴市清泰净化剂有限公司", "endorseeName": "上海碧源化学品有限公司", "isTransfer": "可转让", "endorseDate": "2021-01-21"}, {"title": "转让背书", "endorseName": "上海碧源化学品有限公司", "endorseeName": "安徽巨成精细化工有限公司", "isTransfer": "可转让", "endorseDate": "2021-01-22"}, {"title": "转让背书", "endorseName": "安徽巨成精细化工有限公司", "endorseeName": "爱森(如东)化工有限公司", "isTransfer": "可转让", "endorseDate": "2021-01-26"}, {"title": "转让背书", "endorseName": "爱森(如东)化工有限公司", "endorseeName": "中国三冶集团有限公司", "isTransfer": "可转让", "endorseDate": "2021-03-19"}, {"title": "转让背书", "endorseName": "中国三冶集团有限公司", "endorseeName": "铁西区玫美工程机械租赁站", "isTransfer": "可转让", "endorseDate": "2021-03-25"}]');
创建永久函数
-- 注意:创建永久函数的时候需要进入到项目的数据库下,我的数据库为“sddw”,如果我们想要更换代码实现逻辑,只需要我们将HDFS文件系统(或者lib目录下的涉及到jar包文件)中的jar文件进行替换,退出hive终端并重新进入即可。-- 第一种方式:将jar包放在hive的lib目录下(这样可能存在jar包冲突,如果maven不涉及到其他依赖的时候可以直接放入到lib目录下)
add jar /opt/module/hive-3.1.2/lib/domain_endorse.jar;
create function endorseudf as 'com.sddw.udf.EndorseUDF';
create function endorsegdf as 'com.sddw.gdf.EndorseGDF';
-- 前提:hive-env.sh
-- export HIVE_AUX_JARS_PATH=/opt/module/hive-3.1.2/lib-- 第二种方式:将jar包上传到HDFS 文件系统(jar包一定包含Maven依赖)
create function endorseudf as 'com.sddw.udf.EndorseUDF' using jar 'hdfs:///sddw/function/domain_endorse.jar'
create function endorsegdf as 'com.sddw.gdf.EndorseGDF' using jar 'hdfs:///sddw/function/domain_endorse.jar'
create function endorseudtf as 'com.sddw.udtf.EndorseUDTF' using jar 'hdfs:///sddw/function/domain_endorse.jar'-- 查看创建的函数
show functions like '*endorse*' ;-- 删除函数
drop function if exists sddw.endorseudf;
drop function if exists sddw.endorsegdf;
drop function if exists sddw.endorseudtf;
-- 测试:
select sddw.endorseudtf('[{"title": "转让背书", "endorseName": "江苏普莱姆新材料有限公司", "endorseeName": "邯郸市邯山区润川贸易有限公司", "isTransfer": "可转让", "endorseDate": "2020-12-24"}, {"title": "转让背书", "endorseName": "邯郸市邯山区润川贸易有限公司", "endorseeName": "宁波久营贸易有限公司", "isTransfer": "可转让", "endorseDate": "2020-12-25"}, {"title": "转让背书", "endorseName": "宁波久营贸易有限公司", "endorseeName": "嵊州市恒鑫金属制管有限公司", "isTransfer": "可转让", "endorseDate": "2020-12-25"}, {"title": "转让背书", "endorseName": "嵊州市恒鑫金属制管有限公司", "endorseeName": "建龙北满特殊钢有限责任公司", "isTransfer": "可转让", "endorseDate": "2020-12-25"}, {"title": "转让背书", "endorseName": "建龙北满特殊钢有限责任公司", "endorseeName": "无锡容大环境科技有限公司", "isTransfer": "可转让", "endorseDate": "2020-12-31"}, {"title": "转让背书", "endorseName": "无锡容大环境科技有限公司", "endorseeName": "宜兴市清泰净化剂有限公司", "isTransfer": "可转让", "endorseDate": "2021-01-19"}, {"title": "转让背书", "endorseName": "宜兴市清泰净化剂有限公司", "endorseeName": "上海碧源化学品有限公司", "isTransfer": "可转让", "endorseDate": "2021-01-21"}, {"title": "转让背书", "endorseName": "上海碧源化学品有限公司", "endorseeName": "安徽巨成精细化工有限公司", "isTransfer": "可转让", "endorseDate": "2021-01-22"}, {"title": "转让背书", "endorseName": "安徽巨成精细化工有限公司", "endorseeName": "爱森(如东)化工有限公司", "isTransfer": "可转让", "endorseDate": "2021-01-26"}, {"title": "转让背书", "endorseName": "爱森(如东)化工有限公司", "endorseeName": "中国三冶集团有限公司", "isTransfer": "可转让", "endorseDate": "2021-03-19"}, {"title": "转让背书", "endorseName": "中国三冶集团有限公司", "endorseeName": "铁西区玫美工程机械租赁站", "isTransfer": "可转让", "endorseDate": "2021-03-25"}]');-- 输出:
上海碧源化学品有限公司,中国三冶集团有限公司,无锡容大环境科技有限公司,江苏普莱姆新材料有限公司,建龙北满特殊钢有限责任公司,铁西区玫美工程机械租赁站,邯郸市邯山区润川贸易有限公司,宁波久营贸易有限公司,爱森(如东)化工有限公司,宜兴市清泰净化剂有限公司,安徽巨成精细化工有限公司,嵊州市恒鑫金属制管有限公司
UDF|GDF数据行转列
-- 要想UDF、GDF也实现UDTF这种输出,需要对该数据进行行转列处理
select
corp_name
from
(
select '上海碧源化学品有限公司,中国三冶集团有限公司,无锡容大环境科技有限公司,江苏普莱姆新材料有限公司,建龙北满特殊钢有限责任公司,铁西区玫美工程机械租赁站,邯郸市邯山区润川贸易有限公司,宁波久营贸易有限公司,爱森(如东)化工有限公司,宜兴市清泰净化剂有限公司,安徽巨成精细化工有限公司,嵊州市恒鑫金属制管有限公司' as endorse_coms
)t1 lateral view explode(split(endorse_coms,',')) num as corp_name;
END
到这里,hive的UDF、GDF、UDTF均实现该方法
Hive UDF GDF UDTF编写与实现相关推荐
- Hive自定义UDF UDAF UDTF
Hive是一种构建在Hadoop上的数据仓库,Hive把SQL查询转换为一系列在Hadoop集群中运行的MapReduce作业,是MapReduce更高层次的抽象,不用编写具体的MapReduce方法 ...
- Hive 之 用户自定义函数 UDF UDAF UDTF
一 什么是UDF UDF是UserDefined Function 用户自定义函数的缩写.Hive中除了原生提供的一些函数之外,如果还不能满足我们当前需求,我们可以自定义函数. 除了UDF 之外,我们 ...
- hive java udf_hive java编写udf函数
(一)创建JAVA 代码--例子 package hiveOpt; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoo ...
- Hive常用函数、列转行与行转列、开窗函数、UDF、UDTF
Hive函数.开窗函数.UDF.UDTF 1.系统内置函数 2.常用函数 2.1.关系运算 2.2.数值运算 2.3.条件函数 2.4.日期函数 2.5.字符串函数 2.6.Hive求WordCoun ...
- hive的udf,udaf,udtf各自依賴兩種class(转载+分析整理)
Hive自定义函数包括三种UDF.UDAF.UDTF 名稱縮寫 特點 依賴 UDF(User-Defined-Function) 一进一出 org.apache.hadoop.hive.ql.exec ...
- Hive UDF,就这
摘要:Hive UDF是什么?有什么用?怎么用?什么原理?本文从UDF使用入手,简要介绍相关源码,UDF从零开始. 本文分享自华为云社区<Hive UDF,就这>,作者:汤忒撒. Hive ...
- udf,udaf,udtf之间的区别
1.UDF:用户定义(普通)函数,只对单行数值产生作用: 继承UDF类,添加方法 evaluate() /*** @function 自定义UDF统计最小值* @author John**/publi ...
- UDF UDAF UDTF 区别
UDF UDAF UDTF 区别 UDF 概念: User-Defined-Function 自定义函数 .一进一出:只对单行数据产生作用: 实际使用时,UDF函数以匿名函数的形式进行操作使用 背景: ...
- CDH 创建Hive UDF函数
导入依赖包: hive-exec.jar hadoop-common.jar 注意:函数名必须为 evaluate ,否则hive无法识别! package com.example.hive.udf; ...
最新文章
- Redis入门教程(二)
- Spring boot切换Servlet容器
- C/Cpp / string 截取、替换、查找
- python中字典数据的特点_Python数据类型(字典)
- OpenCV文档阅读笔记-inRange官方解析及实例
- QBC的distinct查询
- 技术人 | 我在支付宝体验技术部这四年学到了什么?
- matlab ofdm qpsk,Matlab关于ofdm系统qpsk调制、awgn信道下的仿真
- bat批处理的注释语句
- 理论篇3:深度学习之----Momentum优化器(2)
- 通过Python绘制分段函数
- 2.PyTorch的Dataset和DataLoader
- ResponseBodyAdvice的使用
- 【Linux系统编程】进程退出和回收进程资源
- 简历c语言项目,C/C++:如何介绍简历中的项目?
- POS--权益证明机制
- 山外山在科创板上市:市值约47亿元,高光勇为实际控制人
- 华为P30、P30pro亲手体验,最新壁纸大曝光!
- java工具多,[转帖]一个 Java 工具到底有多大?
- Jmeter 之 Beanshell