`
zhangxiong0301
  • 浏览: 363868 次
社区版块
存档分类
最新评论

用HIVE中的UDAF实现JSON字符串组装

    博客分类:
  • HIVE
阅读更多

 

      最近有个需求,需要把一个用户的应用使用情况组装成一个GSON字符串,通过UDAF实现了这一功能。具体来说:一张表如下:

meid app usecnt usetime
meid1 com.yulong.x 1 2
meid1 com.baidu.x 2 5
meid2 com.tencent.x 3 8

最终要把同一个用户的应用使用情况做成json串,比如结果中的一条数据如下:

 

{"AppUsageStat": [
        {
            "apName": "cn.kuwo.player",
            "frequency": 9,
            "duration": 312237
        },
        {
            "apName": "com.android.gallery3d",
            "frequency": 3,
            "duration": 70737
        }
    ]
}

 

 

具体代码如下:

package com.yulong;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.parse.SemanticException;
import org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator;
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 org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils;
import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
import org.apache.hadoop.io.Text;



public class MakeCountAndTimeGsonResolver extends AbstractGenericUDAFResolver{
	
	static final Log LOG = LogFactory.getLog( MakeCountAndTimeGsonResolver.class.getName() );

	@Override
	public GenericUDAFEvaluator getEvaluator(TypeInfo[] params) throws SemanticException {
		
		if( params.length != 3 ){
			throw new UDFArgumentTypeException(params.length-1,"Exactly 3 args required,supplied " + params.length );
		}
		
		for( int i = 0 ; i<3 ; i ++  ){
			if( params[i].getCategory() != ObjectInspector.Category.PRIMITIVE ){
				throw new UDFArgumentTypeException(i,"Only primitive type arguments are accepted but "
						+ params[i].getTypeName() + " is passed.");
			}
		}
		return new MakeCountAndTimeGsonEvaluator();
	}


	
	public static class MakeCountAndTimeGsonEvaluator extends GenericUDAFEvaluator{

		private Text gsonRs;
		//3个原始数据行中传入的参数对应ObjectInspector
		private PrimitiveObjectInspector inputOI1;
		private PrimitiveObjectInspector inputOI2;
		private PrimitiveObjectInspector inputOI3;
		//combiner或reducer输入的部分结果对应的ObjectInspector,在Merge方法中用到
		private PrimitiveObjectInspector outputOI;
		
		//存放结果的类,实现AggregationBuffer接口
		public static class GsonAgg implements AggregationBuffer{
			String rs;
			boolean empty;
		}
		
		void resetAgg(GsonAgg result){
			result.empty = true;
			result.rs = "\"AppUsageStat\":[]";
		}
		
		//这个方法返回了UDAF的返回类型,这里确定了MakeCountAndTimeGsonEvaluator自定义函数的返回类型是String类型
		@Override
		public ObjectInspector init(Mode m, ObjectInspector[] parameters)
				throws HiveException {
			
			assert ( parameters.length == 3 ) ;
			super.init(m, parameters);
			gsonRs = new Text( "{\"AppUsageStat:\"[]}" );



//每个阶段都会执行init,不同阶段对应的parameters是不一样的,在map阶段parameters代表的是sql语句中每个udaf对应参数的ObjectInspector,而在combiner或者reducer中parameters代表部分聚合结果对应的ObjectInspector。所以要区分对待。从iterate和merge的参数类型(一个数组类型,一个是object)就能看出来。因此在iterate和merge中分别使用inputOI1/2/3和outputOI 提取对应数据



			if( m == Mode.PARTIAL1 || m == Mode.COMPLETE ){
				inputOI1 = ( PrimitiveObjectInspector ) parameters[0];
				inputOI2 = ( PrimitiveObjectInspector ) parameters[1];
				inputOI3 = ( PrimitiveObjectInspector ) parameters[2];
			}else if( m == Mode.PARTIAL2 || m == Mode.FINAL ){
				outputOI = ( PrimitiveObjectInspector ) parameters[0];
			}
			
			return PrimitiveObjectInspectorFactory.writableStringObjectInspector;
		}

		//创建新的聚合计算的需要的内存,用来存储mapper,combiner,reducer运算过程中的结果
		@Override
		public AggregationBuffer getNewAggregationBuffer() throws HiveException {
			
			GsonAgg result = new GsonAgg();
			reset(result);
			return result;
		}

		//map阶段调用,只要把保存当前的对象agg,再加上输入的参数,就可以了。
		@Override
		public void iterate(AggregationBuffer result, Object[] parts)
				throws HiveException {
			
			if( parts != null ){
				GsonAgg tmpResult = (GsonAgg)result;
				String pkg = PrimitiveObjectInspectorUtils.getString( parts[0] ,inputOI1 );
				Long count = PrimitiveObjectInspectorUtils.getLong( parts[1] ,  inputOI2 );
				Long time = PrimitiveObjectInspectorUtils.getLong( parts[2] ,  inputOI3 );
				String partialGson = "{\"apName\":\""+pkg+"\",\"frequency\":"+count+",\"duration\":"+time+"}";
				int len = tmpResult.rs.length();
				if( tmpResult.empty ){
					tmpResult.empty = false;
					tmpResult.rs = tmpResult.rs.substring(0,len-1 )+partialGson+"]";
				}else{
					tmpResult.rs = tmpResult.rs.substring(0,len-1 )+","+partialGson+"]";
				}
			}
		}

		//combiner合并map返回的结果,还有reducer合并mapper或combiner返回的结果。
		@Override
		public void merge(AggregationBuffer result, Object partial)
				throws HiveException {
			
			String partialGson = PrimitiveObjectInspectorUtils.getString( partial ,  outputOI ); 
			String partialUsage = partialGson.substring(16 ,  partialGson.length()-1 );
			
			GsonAgg tmpResult = (GsonAgg)result;
			int len = tmpResult.rs.length();
			if( tmpResult.empty ){
				tmpResult.empty = false;
				tmpResult.rs = tmpResult.rs.substring(0,len-2 )+partialUsage+"]";
			}else{
				tmpResult.rs = tmpResult.rs.substring(0,len-2 )+","+partialUsage+"]";
			}
		}

		
		
		@Override
		public void reset(AggregationBuffer arg0) throws HiveException {
			
			GsonAgg  result = (GsonAgg)arg0;
			result.empty = true;
			result.rs = "\"AppUsageStat\":[]";
			
		}

		//reducer返回结果,或者是只有mapper,没有reducer时,在mapper端返回结果。
		@Override
		public Object terminate(AggregationBuffer result) throws HiveException {
			
			if( result != null ){
				gsonRs.set( ((GsonAgg)result).rs );
				return gsonRs;
			}
			return null;
		}

		//mapper结束要返回的结果,还有combiner结束返回的结果
		@Override
		public Object terminatePartial(AggregationBuffer result)
				throws HiveException {
			terminate(result);
			return null;
		}
		
	}
	
	
}

 

 

分享到:
评论

相关推荐

    HIve UDF 说明书

    内置函数部分讲解了Hive中已经实现的一些实用函数,如数学函数、集合函数、类型转换函数、日期函数、条件函数、字符串函数、数据掩码函数以及Misc.函数等。数学函数提供了标准的数学计算功能;集合函数包括如COUNT、...

    hive函数.docx

    - **`get_json_object`**:从JSON字符串中提取值 #### 1.5 对复杂类型函数操作 除了基本的复杂类型函数之外,还可以使用其他函数对复杂类型进行更复杂的操作,如`concat`(连接数组)、`sort_array`(排序数组)等...

    基于Facebook的Hive开发

    这段代码展示了如何创建一个名为`src`的表,该表包含两个字段:`key`和`value`,均使用字符串类型。此外,还指定了分区字段`ds`以及存储位置`/hive/src`,并选择以文本文件的方式存储数据。 ##### 查询表 ```sql ...

    毕业设计物联网实战项目基于Eclipse Theia开源框架开发的物联网在线编程IDE.zip

    【项目资源】: 物联网项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    工具变量-全国分省低空经济高质量发展数据(2012-2023年)

    因文件较多,数据存放网盘,txt文件内包含下载链接及提取码,永久有效。失效会第一时间进行补充。样例数据及详细介绍参见文章:https://blog.csdn.net/T0620514/article/details/146960240

    【ThingsBoard初体验】本地编译踩坑记录.html

    【ThingsBoard初体验】本地编译踩坑记录.html

    社团管理系统的设计与实现(代码+数据库+LW)

    摘  要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对信息管理混乱,出错率高,信息安全性差,劳动强度大,费时费力等问题,采用社团管理系统可以有效管理,使信息管理能够更加科学和规范。 社团管理系统在Eclipse环境中,使用Java语言进行编码,使用Mysql创建数据表保存本系统产生的数据。系统可以提供信息显示和相应服务,其管理员增删改查社团信息和社团信息资料,审核社团预订信息。总之,社团管理系统集中管理信息,有着保密性强,效率高,存储空间大,成本低等诸多优点。它可以降低信息管理成本,实现信息管理计算机化。 关键词:社团管理系统;Java语言;Mysql

    【传感器技术】HPS700A压力传感器数据手册:特性、应用与接口设计

    内容概要:HPS700A是一款高精度气压传感器,具有1.8V到3.6V的工作电压范围,测量压力范围为0到1600KPa,温度范围为-40℃到85℃。它采用MEMS技术并通过I²C接口提供温度和压力数据,内部集成24位ADC进行数字化处理,并内置补偿算法确保数据准确性。传感器具备低功耗特性,待机电流小于0.1μA。该器件广泛应用于便携式气泵、移动气压计、工业压力温度监测等领域。文档详细描述了HPS700A的功能特性、电气参数、命令集、I²C通信协议及其典型应用。 适合人群:电子工程师、硬件开发者以及对高精度气压传感器感兴趣的科研人员。 使用场景及目标:①用于需要精确测量环境压力和温度的应用场合;②帮助工程师理解并掌握I²C接口的使用方法;③适用于开发小型化、低功耗的产品设计。 其他说明:HPS700A出厂时已进行校准,用户通常无需再做额外校正。此外,该传感器支持多种OSR(过采样率)设置,允许用户根据精度需求选择不同的转换时间和功耗水平。同时,提供了详细的引脚定义、封装信息及批量生产规格,方便产品集成与大规模制造。

    Android毕设实战项目基于Android的新闻推荐系统,本科毕业设计项目。.zip

    【项目资源】: 适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    【车载电源技术】基于TI C2000的车载DC/DC转换器解决方案:硬件设计、智能控制算法及便捷调试工具介绍

    内容概要:本文介绍了一款国内首家推出的车载DC/DC转换器解决方案,旨在解决传统电源方案的诸多痛点并助力车载电源智能化升级。硬件设计方面,采用TI C2000系列主控芯片,搭配进口功率器件和高精度采样电路,提供了高可靠性的电源方案,甚至将输入级EMI滤波部分进行了模块化设计,并给出了不同功率等级下的元器件选型表。软件部分实现了电压环、电流环双闭环控制,采用了动态调整算法,创新地使用DMA搬运PWM占空比参数,降低CPU占用率,同时在输入电压异常时自动切换硬件保护模式。上位机工具提供实时数据显示、参数设置、波形分析等功能,开放了协议栈源码,内置自动标定功能。; 适合人群:从事车载电源开发的工程师,尤其是希望提升产品开发效率和技术水平的专业人士。; 使用场景及目标:①硬件工程师可以借鉴模块化设计思路和详细的元器件选型表,优化电路设计;②软件工程师可以从双闭环控制算法、DMA传输机制等方面学习先进的编程技巧;③调试人员利用上位机工具进行便捷高效的参数调整和故障排查。; 其他说明:该方案不仅提供了完整的技术文档支持,而且开放的软件架构和配套调试工具极大地方便了二次开发,提高了开发效率。建议对车载电源开发感兴趣的工程师获取相关资料深入学习。

    【C语言编程】华为C语言面试试卷:涵盖基础语法、指针、内存管理与数据结构的综合考核题库设计

    内容概要:本文档是为华为C语言面试设计的试卷,旨在评估应聘者的C语言掌握程度。试卷分为三个主要部分:选择题、填空题和代码题。选择题涵盖了基础语法、指针、内存管理、数据结构等核心知识点,例如动态内存分配、指针操作、结构体大小、位运算等。填空题进一步考察了指针、函数声明、宏定义、内存管理等实际编程技能。代码题则侧重于算法实现,包括单链表反转、字符串逆序、二分查找、内存拷贝、统计二进制中1的个数、删除链表节点、快速排序、判断回文链表、大端小端检测以及线程安全单例模式的实现。所有题目难度适中且贴近实际开发场景,有助于全面评估应聘者的编程能力和问题解决能力。; 适合人群:具备一定C语言基础,有志于应聘华为或其他相关企业的软件开发岗位的求职者。; 使用场景及目标:①帮助求职者复习C语言基础知识,熟悉常见的面试考点;②通过实际编程题目的练习,提高解决问题的能力;③模拟真实面试环境,提升面试自信心。; 其他说明:此试卷不仅测试应聘者的理论知识,还注重实际编程能力的考察。建议考生在准备过程中,不仅要掌握语法和概念,还要多动手实践,理解每个知识点的具体应用。同时,注意代码的规范性和鲁棒性,确保在面试中能够写出高质量的代码。

    汛期安全知识教育课件教案资料.pptx

    汛期安全知识教育课件教案资料

    《人工智能在智能客服领域的应用方案》

    《人工智能在智能客服领域的应用方案》:在当今数字化时代,企业与客户之间的互动日益频繁,客户服务的质量和效率成为企业竞争的关键因素之一。传统的客服模式面临着诸多挑战,如人工客服成本高昂、工作时间受限、服务质量参差不齐、难以应对大量并发的客户咨询等问题。随着人工智能技术的飞速发展,智能客服应运而生,它能够为企业提供高效、便捷、低成本的客户服务解决方案,极大地提升客户体验和企业运营效率。无论是电商、金融、电信、教育等行业,都可以通过对客服数据的分析,优化自身的业务流程和服务质量,提升企业的竞争力。

    毕业设计物联网实战项目基于ThinkAdmin开发对接中国移动物联网开放平台OneNET的终端管理后台.zip

    【项目资源】: 物联网项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    scipy-0.10.1-cp27-cp27mu-manylinux1_x86_64.whl

    该资源为scipy-0.10.1-cp27-cp27mu-manylinux1_x86_64.whl,欢迎下载使用哦!

    Android毕设实战项目所有Android系统上使用Android12的SplashScreen API.zip

    【项目资源】: 适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    毕业设计物联网实战项目基于Zigbee和NB-Iot作为主要通信方式的物联网平台设计,其中还涉及到了AndroidAPP和物联网云平台的使用.zip

    【项目资源】: 物联网项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    毕设单片机实战项目基于mqtt协议进行信息的交互,并通过UART传至51单片机上,进而对继电器和oled显示屏做出操作.zip

    【项目资源】: 单片机项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    hive电商案例分析30.zip

    hive电商案例分析30.zip

    (源码)基于蓝牙技术的多通道键盘.zip

    # 基于蓝牙技术的多通道键盘 ## 项目简介 在多设备工作环境中,用户常常需要在家庭电脑、工作笔记本或平板电脑之间频繁切换键盘输入,这不仅占用了大量桌面空间,而且操作不便。本项目旨在通过蓝牙技术,设计一款能够同时连接多个设备并实现一键切换的多通道键盘,从而简化用户的操作流程,提高工作效率。 ## 项目的主要特性和功能 1. 多设备连接键盘可以同时连接多达三个不同的设备。 2. 一键切换通过按键即可快速切换输入目标设备。 3. 高性能微控制器采用ATMega32u4微控制器,提供足够的GPIO引脚,支持Arduino编程环境,便于固件开发和升级。 4. 蓝牙模块使用RN42蓝牙模块,确保稳定的设备连接和数据传输。 5. 电压调节器使用MIC4680电压调节器,确保系统稳定供电。 ## 安装使用步骤 1. 硬件准备 获取ATMega32u4微控制器、RN42蓝牙模块、MIC4680电压调节器等硬件组件。 2. 电路设计

Global site tag (gtag.js) - Google Analytics