hive自定义UDTF函数叉分函数

1、介绍

从聚合体日志中需要拆解出来各子日志数据,然后单独插入到各日志子表中。通过表生成函数完成这一过程。

2、定义ForkLogUDTF

2.1 HiveUtil工具类

package com.oldboy.umeng.hive.util;

import com.oldboy.umeng.common.domain.AppStartupLog;
import org.apache.hadoop.hdfs.protocol.RollingUpgradeInfo;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.ArrayList; /**
* hive工具
*/
public class HiveUtil { /**
* 组装对象检查器
*/
public static void popOIs(Class<AppStartupLog> clz,
ArrayList<String> fieldNames,
ArrayList<ObjectInspector> fieldOIs) throws IntrospectionException {
//
BeanInfo bi = Introspector.getBeanInfo(clz);
PropertyDescriptor[] pps = bi.getPropertyDescriptors() ;
for(PropertyDescriptor pp : pps){
String name = pp.getName() ;
Class type = pp.getPropertyType() ;
Method getter = pp.getReadMethod() ;
Method setter = pp.getWriteMethod() ;
if(getter != null && setter != null){
if(type == String.class){
fieldNames.add(name) ;
fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector) ;
}
else if(type == int.class || type == Integer.class){
fieldNames.add(name);
fieldOIs.add(PrimitiveObjectInspectorFactory.javaIntObjectInspector);
}
else if(type == long.class || type == Long.class){
fieldNames.add(name);
fieldOIs.add(PrimitiveObjectInspectorFactory.javaLongObjectInspector);
}
}
}
} /**
* 按照指定的列表顺序组装数组
*/
public static Object[] convert2Arr(AppStartupLog l, ArrayList<String> fieldNames) {
Object[] values = new Object[fieldNames.size()] ;
for(int i = 0 ; i < fieldNames.size() ; i ++){
try {
values[i] = getPropValue(l , fieldNames.get(i)) ;
} catch (Exception e) {
}
}
return values ;
} /**
* 从指定对象中提取指定的属性值
*/
public static Object getPropValue(Object o , String propName) throws Exception {
BeanInfo bi = Introspector.getBeanInfo(o.getClass()) ;
PropertyDescriptor[] pps = bi.getPropertyDescriptors() ;
for(PropertyDescriptor pp : pps){
String name = pp.getName() ;
if(name.equals(propName)){
Method getter = pp.getReadMethod();
if(getter != null){
return getter.invoke(o) ;
}
}
}
return null ;
}
}

2.2 LogUtil工具类

package com.oldboy.umeng.common.util;

import com.alibaba.fastjson.JSON;
import com.oldboy.umeng.common.domain.*; import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.util.*; /**
* 日志工具类
*/
public class LogUtil { private static Random r = new Random(); /**
* 通过内省生成日志对象
*/
public static <T> T genLog(Class<T> t) throws Exception { //创建实例
Object obj = t.newInstance(); BeanInfo bi = Introspector.getBeanInfo(t);
PropertyDescriptor[] pps = bi.getPropertyDescriptors();
//循环所有属性
for (PropertyDescriptor pp : pps) {
//取set方法
Method setter = pp.getWriteMethod();
if (setter != null) {
String pname = pp.getName();
Class ptype = pp.getPropertyType();
//字符串类型
if (ptype == String.class) {
String pvalue = DictUtil.getRandString(pname.toLowerCase());
setter.invoke(obj, pvalue);
} else if (ptype == int.class || ptype == Integer.class) {
try {
int pvalue = DictUtil.getRandInt(pname.toLowerCase());
setter.invoke(obj, pvalue);
} catch (Exception e) {
}
}
}
}
processLogTime(obj);
return (T) obj;
} /**
* 生成实例,不包含父类的内容
*/
public static <T> T genLogNoParents(Class<T> t) throws Exception {
//创建实例
Object obj = t.newInstance();
Field[] fs = t.getDeclaredFields();
for (Field f : fs) {
String fname = f.getName();
Class ftype = f.getType();
if (ftype == String.class) {
String fvalue = DictUtil.getRandString(fname.toLowerCase());
f.setAccessible(true);
f.set(obj, fvalue);
} else if (ftype == int.class || ftype == Integer.class) {
try {
int fvalue = DictUtil.getRandInt(fname.toLowerCase());
f.setAccessible(true);
f.set(obj, fvalue);
} catch (Exception e) {
}
}
}
//处理设备id和时间问题
processLogTime(obj);
return (T) obj;
} /**
* 处理时间
*/
private static void processLogTime(Object obj) {
long now = System.currentTimeMillis();
int dur = 10 * 24 * 60 * 60 * 1000;
long thatTime = now - r.nextInt(dur);
if (obj instanceof AppBaseLog) {
((AppBaseLog) obj).setCreatedAtMs(thatTime);
}
} public static <T> List<T> genLogList(Class<T> t, int n) throws Exception {
List<T> list = new ArrayList<T>();
for (int i = 0; i < n; i++) {
list.add(genLogNoParents(t));
}
return list;
} /**
* 生成日志聚合体
*/
public static AppLogAggEntity getLogAgg() throws Exception {
Random r = new Random();
int n = 5;
AppLogAggEntity agg = genLog(AppLogAggEntity.class);
processsDeviceId(agg);
agg.setStartupLogs(genLogList(AppStartupLog.class, r.nextInt(n) + 1));
agg.setEventLogs(genLogList(AppEventLog.class, r.nextInt(n) + 1));
agg.setErrorLogs(genLogList(AppErrorLog.class, r.nextInt(n) + 1));
agg.setUsageLogs(genLogList(AppUsageLog.class, r.nextInt(n) + 1));
agg.setPageLogs(genLogList(AppPageLog.class, r.nextInt(n) + 1));
return agg;
} /**
* 处理设备id
*/
private static void processsDeviceId(AppLogAggEntity agg) {
//1 - 00001
DecimalFormat df = new DecimalFormat("00000");
int devid = r.nextInt(10000) + 1;
String str = "dv-" + df.format(devid);
agg.setDeviceId(str);
} /**
* 生成特定的类对应的ddl语句
*/
public static String genDDL(Class clazz) throws IntrospectionException {
String RN = "\r\n";
//只含类名
String simpleName = clazz.getSimpleName();
//算表名
String tablename = simpleName.substring(3).toLowerCase() + "s"; StringBuilder builder = new StringBuilder();
builder.append(RN)
.append("--")
.append(tablename).append(RN).append(
"create table if not exists " + tablename).append(RN).append("(").append(RN);
BeanInfo bi = Introspector.getBeanInfo(clazz);
PropertyDescriptor[] pps = bi.getPropertyDescriptors();
for (int i = 0; i < pps.length; i++) {
PropertyDescriptor pp = pps[i];
String name = pp.getName();
Class type = pp.getPropertyType();
Method getter = pp.getReadMethod();
Method setter = pp.getWriteMethod();
if (getter != null && setter != null) {
//不是最后
if (i != pps.length - 1) {
if (type == String.class) {
builder.append(" " + name + "\t\t\t string , " + RN);
} else if (type == int.class || type == Integer.class) {
builder.append(" " + name + "\t\t\t int , " + RN);
} else if (type == long.class || type == Long.class) {
builder.append(" " + name + "\t\t\t bigint , " + RN);
}
} else {
if (type == String.class) {
builder.append(" " + name + "\t\t\t string " + RN);
} else if (type == int.class || type == Integer.class) {
builder.append(" " + name + "\t\t\t int " + RN);
} else if (type == long.class || type == Long.class) {
builder.append(" " + name + "\t\t\t bigint " + RN);
}
}
}
}
//追加结束符
builder.append(")")
.append(RN)
.append("partitioned by (ym int ,day int , hm int) ")
.append(RN)
.append("stored as parquet ;")
.append(RN) ; return builder.toString() ;
} /**
* 生成所有的DDL语句
*/
public static String genAllDDL() throws IntrospectionException {
Class[] clazz = {
AppStartupLog.class ,
AppEventLog.class ,
AppErrorLog.class ,
AppUsageLog.class ,
AppPageLog.class ,
} ; StringBuilder builder = new StringBuilder() ;
builder.append("use umeng_big11 ;") ;
builder.append("\r\n") ;
for(Class clz : clazz){
builder.append(genDDL(clz)) ;
}
return builder.toString() ;
} /**
* 从json个数反串行化日志
*/
public static AppLogAggEntity deserLog(String json){
String newJson = json.replace("\\\"" , "\"") ;
AppLogAggEntity agg = JSON.parseObject(newJson , AppLogAggEntity.class) ;
return agg ;
} /**
* 合并聚合体中公共属性到每个日志实体中。
*/
public static void mergeProp(AppLogAggEntity agg) throws Exception {
List<AppBaseLog> sublogs = new ArrayList<AppBaseLog>() ;
sublogs.addAll(agg.getStartupLogs());
sublogs.addAll(agg.getErrorLogs());
sublogs.addAll(agg.getEventLogs());
sublogs.addAll(agg.getUsageLogs());
sublogs.addAll(agg.getPageLogs()); for(AppBaseLog log : sublogs){
doMergeProper(agg, log) ;
}
} /**
* 将a的属性合并到b上去
*/
private static void doMergeProper(Object a , Object b ) throws Exception {
//
Map<String, Method> bcache = new HashMap<String, Method>() ; //提取b的属性集合
BeanInfo b_bi = Introspector.getBeanInfo(b.getClass()) ;
PropertyDescriptor[] b_pps = b_bi.getPropertyDescriptors();
for(PropertyDescriptor pp : b_pps){
String pname = pp.getName() ;
Method setter = pp.getWriteMethod() ;
if(setter != null){
bcache.put(pname,setter) ;
}
} BeanInfo bi = Introspector.getBeanInfo(a.getClass()) ;
PropertyDescriptor[] pps = bi.getPropertyDescriptors() ;
for(PropertyDescriptor pp : pps){
String name = pp.getName() ;
Class type = pp.getPropertyType() ;
Method getter = pp.getReadMethod() ;
Method setter = pp.getWriteMethod() ;
if(getter != null
&& setter != null
&& (type == String.class
|| type == int.class
|| type == Integer.class
|| type == long.class
|| type == Long.class)){
Object value = getter.invoke(a) ;
Method b_set = bcache.get(name) ;
if(b_set != null){
Class[] ptype = b_set.getParameterTypes();
if(ptype != null && ptype.length == 1){
if(ptype[0] == type){
b_set.setAccessible(true);
b_set.invoke(b ,value ) ;
}
}
}
}
}
}
}

2.3 ForkLogUDTF

package com.oldboy.umeng.hive.udf;

import com.oldboy.umeng.common.domain.AppLogAggEntity;
import com.oldboy.umeng.common.domain.AppStartupLog;
import com.oldboy.umeng.common.util.LogUtil;
import com.oldboy.umeng.hive.util.HiveUtil;
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.*;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; import java.beans.IntrospectionException;
import java.util.ArrayList;
import java.util.List; /**
* 自定义日志叉分函数
*/
public class ForkLogUDTF extends GenericUDTF{ //存放字段名称列表
ArrayList<String> fieldNames ; //字段对应的对象检查器
ArrayList<ObjectInspector> fieldOIs ; //转换器数组
ObjectInspectorConverters.Converter[] converters = new ObjectInspectorConverters.Converter[4] ; /**
* 判断参数合法性 , 定义输出表结构 , 准备转换器
*/
public StructObjectInspector initialize(ObjectInspector[] args)
throws UDFArgumentException {
if(args.length != 4){
throw new UDFArgumentException("参数个数不对,需要4个参数!!") ;
} if(args[0].getCategory() != ObjectInspector.Category.PRIMITIVE
|| ((PrimitiveObjectInspector)args[0]).getPrimitiveCategory()
!= PrimitiveObjectInspector.PrimitiveCategory.STRING){
throw new UDFArgumentException("第一个参数需要string类型");
}
if(args[1].getCategory() != ObjectInspector.Category.PRIMITIVE
|| ((PrimitiveObjectInspector)args[1]).getPrimitiveCategory() != PrimitiveObjectInspector.PrimitiveCategory.LONG){
throw new UDFArgumentException("第二参数需要long类型");
}
if(args[2].getCategory() != ObjectInspector.Category.PRIMITIVE
|| ((PrimitiveObjectInspector)args[2]).getPrimitiveCategory() != PrimitiveObjectInspector.PrimitiveCategory.STRING){
throw new UDFArgumentException("第三个参数需要string类型");
}
if(args[3].getCategory() != ObjectInspector.Category.PRIMITIVE
|| ((PrimitiveObjectInspector)args[3]).getPrimitiveCategory() != PrimitiveObjectInspector.PrimitiveCategory.STRING){
throw new UDFArgumentException("第四个参数需要string类型");
} //正常处理
//处理输入的OI
converters[0] = ObjectInspectorConverters.getConverter(args[0] , PrimitiveObjectInspectorFactory.javaStringObjectInspector) ;
converters[1] = ObjectInspectorConverters.getConverter(args[1] , PrimitiveObjectInspectorFactory.javaLongObjectInspector) ;
converters[2] = ObjectInspectorConverters.getConverter(args[2] , PrimitiveObjectInspectorFactory.javaStringObjectInspector) ;
converters[3] = ObjectInspectorConverters.getConverter(args[3] , PrimitiveObjectInspectorFactory.javaStringObjectInspector) ; //输出表结构
fieldNames = new ArrayList<String>();
fieldOIs = new ArrayList<ObjectInspector>(); //组装对象检查器集合
try {
HiveUtil.popOIs(AppStartupLog.class , fieldNames , fieldOIs);
} catch (IntrospectionException e) {
e.printStackTrace();
}
return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs);
} public void process(Object[] args) throws HiveException {
if (args.length != 4) {
throw new UDFArgumentException("参数个数不对,需要4个参数!!");
}
String servertimestr = (String)converters[0].convert(args[0]);
long clienttimems = (Long)converters[1].convert(args[1]);
String clientip = (String)converters[2].convert(args[2]);
String log= (String)converters[3].convert(args[3]); //反序列化聚合体
AppLogAggEntity agg = LogUtil.deserLog(log) ;
try {
//合并属性
LogUtil.mergeProp(agg);
List<AppStartupLog> logs = agg.getStartupLogs() ;
for(AppStartupLog l : logs){
forward(HiveUtil.convert2Arr( l , fieldNames));
}
} catch (Exception e) {
e.printStackTrace();
}
} public void close() throws HiveException {
}
}

3、导出jar包部署到hive/lib目录下

4、在hive中注册函数

4.1 添加jar到类路径

$hive>add jar /soft/hive/umeng_hive.jar ;

4.2 注册函数

$hive>create function forklogs as 'com.oldboy.umeng.hive.udf.ForkLogUDTF' ;

4.3 调用函数,查看结果

$hive>use umeng_big11 ;
$hive>select forklogs(servertimestr , clienttimems , clientip ,log) from raw_logs ;

hive自定义UDTF函数叉分函数的更多相关文章

  1. Hive 自定义函数 UDF UDAF UDTF

    1.UDF:用户定义(普通)函数,只对单行数值产生作用: 继承UDF类,添加方法 evaluate() /** * @function 自定义UDF统计最小值 * @author John * */ ...

  2. hive自定义函数UDF UDTF UDAF

    Hive 自定义函数 UDF UDTF UDAF 1.UDF:用户定义(普通)函数,只对单行数值产生作用: UDF只能实现一进一出的操作. 定义udf 计算两个数最小值 public class Mi ...

  3. Hive 自定义函数

    hive 支持自定义UDF,UDTF,UDAF函数 以自定义UDF为例: 使用一个名为evaluate的方法 package com.hive.custom; import org.apache.ha ...

  4. hive -- 自定义函数和Transform

    hive -- 自定义函数和Transform UDF操作单行数据, UDAF:聚合函数,接受多行数据,并产生一个输出数据行 UDTF:操作单个数据 使用udf方法: 第一种: add jar xxx ...

  5. hive自定义函数学习

    1介绍 Hive自定义函数包括三种UDF.UDAF.UDTF UDF(User-Defined-Function) 一进一出 UDAF(User- Defined Aggregation Funcat ...

  6. Hive自定义函数的学习笔记(1)

    前言: hive本身提供了丰富的函数集, 有普通函数(求平方sqrt), 聚合函数(求和sum), 以及表生成函数(explode, json_tuple)等等. 但不是所有的业务需求都能涉及和覆盖到 ...

  7. hive自定义函数(UDF)

    首先什么是UDF,UDF的全称为user-defined function,用户定义函数,为什么有它的存在呢?有的时候 你要写的查询无法轻松地使用Hive提供的内置函数来表示,通过写UDF,Hive就 ...

  8. hive常用函数 wordCount--Hive窗口函数1.1.1 聚合开窗函数聚合开窗函数实战

    第三天笔记 第三天笔记 SQL练习Hive 常用函数关系运算数值计算条件函数日期函数重点!!!字符串函数Hive 中的wordCount1.1 Hive窗口函数1.1.1 聚合开窗函数聚合开窗函数实战 ...

  9. Hive(六)内置函数与高级操作

    一内置函数 1 数学函数 Return Type Name (Signature) Description DOUBLE round(DOUBLE a) Returns the rounded BIG ...

随机推荐

  1. Unity 关节

    引言 关节组件一共分为5大类,它们分别是链条关节.固定关节.弹簧关节.角色关节和可配置关节. 链条关节(Hinge Joint):将两个物体以链条的形式绑在一起,当力量过大超过链条的固定力矩时,两个物 ...

  2. Python内置函数、作用域、闭包、递归

    1.几个可能用到的内置函数 2.函数内变量的作用域 3.内嵌函数和闭包 4.递归函数 1.常见的内置函数 常见的内置函数:    查看内置函数:        print(dir(__builtins ...

  3. Python语言、编译解释、动态库静态库、编译过程、头文件

    学习Python这门语言首先要了解 什么是编译与解释,什么是连接,什么是动态库与静态库, 什么是编译: 编译就是先把高级语言设计的程序翻译成二进制的机器语言,然后CPU直接执行机器码就可以了.一把翻译 ...

  4. Til the Cows Come Home (dijkstra算法)

    Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before ...

  5. Codeforces Round #482 (Div. 2) B、Treasure Hunt(模拟+贪心)979B

    题目 大致题意 n表示要进行n次操作,接着给出三个字符串,表示三个人初始拥有的串.每次操作要替换字符串中的字母,询问最后在游戏中曾出现过的相同的子串谁最多. 思路 (1)  讨论最多的子串,肯定是全部 ...

  6. js实现放大镜效果

    原理: 鼠标在小图片上移动时,通过捕捉鼠标在小图片上的位置,定位大图片的相应位置: 放大镜的移动方向和大图片的移动方向:横向和纵向都是相反,才可以保证同步: 需要元素:大图和小图,存放大图和小图的容器 ...

  7. var在IE中的问题

    一个朋友问了一个js问题, 一段看不出有任何问题的代码, 在ie下报错:”object doesn’t support this property or method”. function foo(o ...

  8. @ControllerAdvice 拦截异常并统一处理

    在spring 3.2中,新增了@ControllerAdvice 注解,可以用于定义@ExceptionHandler.@InitBinder.@ModelAttribute,并应用到所有@Requ ...

  9. python 利用正则表达的式提取特定数据如手机号

    import re file=open('1.txt','r') listfile=file.readlines() listfile=','.join(listfile)#合并文本 listfile ...

  10. gcc标准,c++中的inline

    1. GCC的inlinegcc对C语言的inline做了自己的扩展,其行为与C99标准中的inline有较大的不同. 1.1. static inlineGCC的static inline定义很容易 ...