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. Subversion Server Edge的安装使用

    1.Subversion Server Edge的搭建 当在操作系统为64位的配置服务器上部署时只能够选择Collabnet Subversion Edge,它集合了Subversion所需要一切资源 ...

  2. hdu6223 Infinite Fraction Path 2017沈阳区域赛G题 bfs加剪枝(好题)

    题目传送门 题目大意:给出n座城市,每个城市都有一个0到9的val,城市的编号是从0到n-1,从i位置出发,只能走到(i*i+1)%n这个位置,从任意起点开始,每走一步都会得到一个数字,走n-1步,会 ...

  3. canvas基础入门(一)canvas的width、height于css样式中的宽高区别

    canvas的width.height于css样式中的宽高对画布的内容显示是有所区别的 1.在canvas标签下调用他的width和height,而且是没有单位的宽高,这种指定canvas大小的方法也 ...

  4. 使用springmvc时处理404的方法

    使用springmvc时处理404的方法 来源: https://www.cnblogs.com/handsome-man/p/5519439.html,再次申明不是我原创的,尊重原创 如何定义404 ...

  5. c++ primer 中讲的顶层const 和 底层 const 理解

    c++ primer 中讲的    顶层const 和 底层 const   以前没搞懂的顶层const和底层const,这次看了后感觉明白了. 首先,const是一个限定符,被它修饰的变量的值不能改 ...

  6. JqGrid查询数据为空时给表格添加提示信息

    在JqGrid的loadComplete事件中添加下面的代码就可以实现上图的效果 loadComplete: function () { var rowNum = $("#purchaser ...

  7. java高级篇

    Method对象可以得到任何一个类的任何方法的定义(只需要传入方法的名字和参数即可) class Ming { private void speak() { System.out.println(&q ...

  8. maya 安装不上

    AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...

  9. C/C++中 static 的作用

    在C中,有三个作用: 1.修饰全局变量: 作用是隐藏,也就是这个全局变量仅在本文件中可见. 2.修饰局部变量: 作用是扩展变量的生存期,令这个局部变量成为静态的. 3.修饰函数: 作用是隐藏,将此函数 ...

  10. JEECMS站群管理系统-- Jeecms项目导入myeclipse

    1.在myeclipse中新建一个项目jeecms,将服务器中jeecms项目下web-inf文件夹下内容拷到新建项目中 解压缩jeecms-3.0.2-final-src,在src文件夹下会看到有三 ...