Hive内置运算函数,自定义函数(UDF)和Transform(大数据学习20)

当Hive提供的内置函数无法满足你的业务处理需要时,此时就可以考虑使用用户自定义函数(UDF(UDF:user defined function).

自定义函数类别

UDF  作用于单个数据行,产生一个数据行作为输出。(数学函数,字符串函数)

UDAF(用户定义聚集函数):接收多个输入数据行,并产生一个输出数据行。(count,max)

UDF开发实例:

客户需求: 现有一个json脚本,需要将里面的字符串解析存储到Hive仓库中,要求每个字段对应相应的数据,并且将其中时间字段对应的数据转换成天数。

json 脚本:https://pan.baidu.com/s/1j7UnzJir155YVXmWDIsGvw   提取码: 6r29

通过上面的需求,我们知道hive提供的内置函数已经无法满足客户需求,所以这时需要我们自行定义内置函数。

使用IDEA进行代码编写   JsonParser 类继承UDF类 、 MovieRateBean类

  包结构:

  MovieRateBean类

package com.lyz.bigdata.udf;
/**
 *@Author:[email protected] Lyz
 *@Date: 2019/3/18 12:43
 *@Description:
 **/
//{"movie":"1721","rate":"3","timeStamp":"965440048","uid":"5114"}
public class MovieRateBean{
    private String movie;
    private String rate;
    private String timeStamp;
    private String uid;

    public String getMovie() {
        return movie;
    }

    public void setMovie(String movie) {
        this.movie = movie;
    }

    public String getRate() {
        return rate;
    }

    public void setRate(String rate) {
        this.rate = rate;
    }

    public String getTimeStamp() {
        return timeStamp;
    }

    public void setTimeStamp(String timeStamp) {
        this.timeStamp = timeStamp;
    }

    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }
    @Override
    public String toString() {
        return movie + "\t" + rate + "\t" + timeStamp + "\t" + uid;
    }

}

  JsonParser 类

package com.lyz.bigdata.udf;

import org.apache.hadoop.hive.ql.exec.UDF;
import org.codehaus.jackson.map.ObjectMapper;

import java.io.IOException;

/**
 *@Author:[email protected] Lyz
 *@Date: 2019/3/18 9:56
 *@Description:
 **/
public class JsonParser  extends UDF {

   public  String  evaluate(String jsonLine){

       ObjectMapper objectMapper = new ObjectMapper();
       try {
           MovieRateBean bean = objectMapper.readValue(jsonLine, MovieRateBean.class);
           return  bean.toString();
       } catch (IOException e) {
           e.printStackTrace();
       }
          return "";
   }
}

 将上述打包成jar包,上传到HDFS中,并且将json的数据也导入HDFS中

上述打的jar包:  https://pan.baidu.com/s/1ltOrO9dtcKhSZZ3StDRiYQ   提取码: ivc6

启动hive数据仓库,然后在里面创建一个表,来后将json数据集导入表中,先将他们解析成一条一条的字符串 

操作命令

create table t_json(line string) row format delimited;

load data local inpath '/home/hadoop/rating.json' into table t_json;


select * from t_json limit 10;  //因为数据量过大,所以只显示10条


导入表中 因为这些数据现在只是字符串形式,所以需要将他们解析成数据库的字段形式,每个字段对应响应的数据

这时候将要用到我们定义的函数。 操作步骤如下:

命令如下:

add JAR /home/hadoop/hiveudf.jar;  

create temporary function parsejson as'com.lyz.bigdata.udf.JsonParser';  //parsejson 是起的函数名

select parsejson(line) from t_json limit 10;

我们可以看到,用函数解析之后,因为没有字符分割,所以只是将数据给整理好,但是对应的字段没有显示出来,所以接下来 我们需要重新创建一个表,然后分割成四段,让每一段数据对应他的字段

命令如下:

create table t_rating as
select split(parsejson(line),'\t')[0]as movieid,
split(parsejson(line),'\t')[1] as rate,
split(parsejson(line),'\t')[2] as timestring,
split(parsejson(line),'\t')[3] as uid from t_json limit 10;



执行完之后进行查询:

select * from t_rating limit 10;

查询结果如下:

接下来我们实现客户的另一个需求 将时间字段对应的秒改为天

技术实现:Hive的 Transform 关键字提供了在SQL中调用自写脚本的功能适合实现Hive中没有的功能又不想写UDF的情况

现在使用Transform关键字来实现

1.创建一个python脚本  然后在HDFS中创建一个文件将脚本复制进去并保存, 文件命名为weekday_mapper.py

#!/bin/python
import sys
import datetime

for line in sys.stdin:
  line=line.strip()
  movieid,rating,unixtime,userid = line.split('\t')
  weekday = datetime.datetime.fromtimestamp(float(unixtime)).isoweekday()
  print '\t'.join([movieid,rating,str(weekday),userid])

  

  2.将脚本添加到指定路径下  3. 重新创建一个表  使用上述的python 脚本  4.待程序执行完之后进行查询  相应指令如下:   

命令如下:

add FILE /home/hadoop/weekday_mapper.py;


create table u_data_new as select transform(movieid,rate,timestring,uid)
using 'python weekday_mapper.py' as (movieid,rate,weekday,uid) from t_rating;



select * from u_data_new limit 10;

从表中我们可以看到时间由秒变成了天   实现了客户的需求!

 

猜你喜欢

转载自blog.csdn.net/weixin_38201936/article/details/88635734