使用Hive中自定义UDAF函数实现统计区域产品用户访问排名

UDAF实现方法: 
1,用户的UDAF必须继承了org.apache.hadoop.hive.ql.exec.UDAF;
2,用户的UDAF必须包含至少一个实现了org.apache.hadoop.hive.ql.exec的静态类,诸如实现了 UDAFEvaluator 
3,一个计算函数必须实现的5个方法的具体含义如下:
init():主要是负责初始化计算函数并且重设其内部状态,一般就是重设其内部字段。一般在静态类中定义一个内部字段来存放最终的结果。
iterate():每一次对一个新值进行聚集计算时候都会调用该方法,计算函数会根据聚集计算结果更新内部状态。当输 入值合法或者正确计算了,则       就返回true。
terminatePartial():Hive需要部分聚集结果的时候会调用该方法,必须要返回一个封装了聚集计算当前状态的对象。
merge():Hive进行合并一个部分聚集和另一个部分聚集的时候会调用该方法。
terminate():Hive最终聚集结果的时候就会调用该方法。计算函数需要把状态作为一个值返回给用户。

mapreduce阶段调用函数 
MAP 

init() 
iterate() 
terminatePartial()

Combiner 

merge() 
terminatePartial()

REDUCE 

init() 
merge() 
terminate()

一、自定义UDAF函数

点击( 此处 )折叠或打开
  1. package hive.org.ruozedata;

  2. import java.util.*;

  3. import org.apache.hadoop.hive.ql.exec.UDAF;
  4. import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;
  5. import org.apache.log4j.Logger;

  6.     public class UserClickUDAF extends UDAF {

  7.     // 日志对象初始化
  8.     public static Logger logger = Logger.getLogger(UserClickUDAF.class);

  9.     // 静态类实现UDAFEvaluator
  10.     public static class Evaluator implements UDAFEvaluator {
  11.         // 设置成员变量,存储每个统计范围内的总记录数
  12.         private static Map<String, String> courseScoreMap;

  13.         private static Map<String, String> city_info;
  14.         private static Map<String, String> product_info;
  15.         private static Map<String, String> user_click;

  16.         //初始化函数,map和reduce均会执行该函数,起到初始化所需要的变量的作用
  17.         public Evaluator() {
  18.             init();
  19.         }

  20.         // 初始化函数间传递的中间变量
  21.         public void init() {
  22.             courseScoreMap = new HashMap<String, String>();
  23.             city_info = new HashMap<String, String>();
  24.             product_info = new HashMap<String, String>();
  25.        }

  26.         //map阶段,返回值为boolean类型,当为true则程序继续执行,当为false则程序退出
  27.         public boolean iterate(String pcid, String pcname, String pccount) {
  28.             if (pcid == null || pcname == null || pccount == null) {
  29.                 return true;
  30.             }

  31.             if (pccount.equals("-1")) {
  32.                 // 城市表
  33.                 city_info.put(pcid, pcname);
  34.             }
  35.             else if (pccount.equals("-2")) {
  36.                 // 产品表
  37.                 product_info.put(pcid, pcname);
  38.             }
  39.             else
  40.             {
  41.                 // 处理用户点击关联
  42.                 unionCity_Prod_UserClic1(pcid, pcname, pccount);
  43.            }
  44.             return true;
  45.         }

  46.         // 处理用户点击关联
  47.         private void unionCity_Prod_UserClic1(String pcid, String pcname, String pccount) {
  48.             if (product_info.containsKey(pcid)) {
  49.                 if (city_info.containsKey(pcname)) {
  50.                     String city_name = city_info.get(pcname);
  51.                     String prod_name = product_info.get(pcid);
  52.                     String cp_name = city_name + prod_name;

  53.                     // 如果之前已经Put过Key值为区域信息,则把记录相加处理
  54.                     if (courseScoreMap.containsKey(cp_name)) {
  55.                         int pcrn = 0;
  56.                         String strTemp = courseScoreMap.get(cp_name);
  57.                         String courseScoreMap_pn = strTemp.substring(strTemp.lastIndexOf("\t".toString())).trim();
  58.                         pcrn = Integer.parseInt(pccount) + Integer.parseInt(courseScoreMap_pn);

  59.                         courseScoreMap.put(cp_name, city_name + "\t" + prod_name + "\t" + Integer.toString(pcrn));
  60.                     }
  61.                     else {
  62.                         courseScoreMap.put(cp_name, city_name + "\t" + prod_name + "\t" + pccount);
  63.                     }
  64.                 }
  65.             }
  66.         }

  67.         /**
  68.          * 类似于combiner,在map范围内做部分聚合,将结果传给merge函数中的形参mapOutput
  69.          * 如果需要聚合,则对iterator返回的结果处理,否则直接返回iterator的结果即可
  70.          */
  71.         public Map<String, String> terminatePartial() {
  72.             return courseScoreMap;
  73.         }

  74.         // reduce 阶段,用于逐个迭代处理map当中每个不同key对应的 terminatePartial的结果
  75.         public boolean merge(Map<String, String> mapOutput) {
  76.             this.courseScoreMap.putAll(mapOutput);
  77.             return true;
  78.         }
  79.         // 处理merge计算完成后的结果,即对merge完成后的结果做最后的业务处理
  80.         public String terminate() {
  81.             return courseScoreMap.toString();
  82.         }
  83.     }
  84. }
二、使用添加Jar包与Hive中临时函数
点击( 此处 )折叠或打开
  1. DROP TEMPORARY FUNCTION user_click;

  2. add jar /data/hive_udf-1.0.jar;

  3. CREATE TEMPORARY FUNCTION user_click AS 'hive.org.ruozedata.UserClickUDAF';
三、 调用自定义UDAF函数处理数据

点击(此处)折叠或打开

  1. insert overwrite directory '/works/tmp1' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
  2. select regexp_replace(substring(rs, instr(rs, '=')+1), '}', '') from (
  3.   select explode(split(user_click(pcid, pcname, type),',')) as rs from (
  4.     select * from (
  5.       select '-2' as type, product_id as pcid, product_name as pcname from product_info
  6.       union all
  7.       select '-1' as type, city_id as pcid,area as pcname from city_info
  8.       union all
  9.       select count(1) as type,
  10.              product_id as pcid,
  11.              city_id as pcname
  12.         from user_click
  13.        where action_time='2016-05-05'
  14.       group by product_id,city_id
  15.     ) a
  16.   order by type) b
  17. ) c
四、 创建Hive临时外部表

点击(此处)折叠或打开

  1. create external table tmp1(
  2. city_name string,
  3. product_name string,
  4. rn string
  5. )
  6. ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
  7. location '/works/tmp1';
五、 -统计最终区域前3产品排名

点击(此处)折叠或打开

  1. select * from (
  2. select city_name,
  3.        product_name,
  4.        floor(sum(rn)) visit_num,
  5.        row_number()over(partition by city_name order by sum(rn) desc) rn,
  6.        '2016-05-05' action_time
  7.   from tmp1
  8.  group by city_name,product_name
  9. ) a where rn <=3
六、统计结果


此方法可能不会很好,但最少可以起到一定的抛砖引玉的功效。希望大家不吝赐教!



若泽大数据交流群:671914634


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31511218/viewspace-2150561/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/31511218/viewspace-2150561/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值