SparkSQL中的UDF

一、UDF(User Defined Function):spark SQL中用户自定义函数,用法和spark SQL中的内置函数类似;是saprk SQL中内置函数无法满足要求,用户根据业务需求自定义的函数。

二、UDF使用分为两步:

(1)自定义UDF类,根据业务需要,实现UDF1/2/3....22中的接口之一,其中UDF后跟的数字,
比如UDF1、UDF2;表示输入参数的个数,1表示有一个入参,2表示有两个入参,
最多可传入22个输入参数。如:
public class 自定义UDF类名 implements UDF3<String,String,String,String>{
    @override
    public String call(String p1,String p2,String p3)throw Exception{}
} 
其中UDF3中前三个参数表示输入参数的数据类型,最后的参数用于指定call方法的返回值类型
(2)注册UDF函数:
//创建配置
SparkConf conf = new SparkConf()
         .setAppName("openwindowFunctionDemo");
//创建提交spark应用的集群入口类对象
JavaSparkContext sc = new JavaSparkContext(conf);
//创建SQLContext对象
SQLContext sqlContext = new SQLContext(sc.sc());
//注册getJsonData自定义函数
/**
* register方法三个参数中,第一个参数指定自定义函数名,
* 第二个参数传入一个自定义函数对象;第三个参数指定返回值类型
*
*/
sqlContext.udf().register("getJsonData",new GetJsonDataUDF(), DataTypes.StringType);
(3)通过sqlContext.sql(sql语句)使用上述注册的UDF函数

三、具体案例:

 /**
         * 假如spark sql注册过一张临时表user,其数据格式如下
         * id       userInfo
         * 001      {'username':'tom','age':'12','sex':'男'}
         * 002      {'username':'henry','age':'18','sex':'男'}
         * 003      {'username':'jack','age':'32','sex':'男'}
         * 及user表中userInfo存储的数据格式为json格式,如果需要单独获取userInfo里的username;
         * spark sql内置的函数无法满足我们的需要,这时就可以通过自定函数来实现上述需求
         */
(1)自定义UDF类:
public class GetJsonDataUDF implements UDF2<String,String,String>{
    @Override
    public String call(String json, String field) throws Exception {
        //构建json对象
        JSONObject jsonObject = JSONObject.parseObject(json);
        //根据字段名获取其对应的value
        return jsonObject.getString(field);
    }

}
(2)注册UDF函数并使用
  
public class Test {
    public static void main(String[] args) {
        //创建配置
        SparkConf conf = new SparkConf()
                .setAppName("openwindowFunctionDemo");

        //创建提交spark应用的集群入口类对象
        JavaSparkContext sc = new JavaSparkContext(conf);
        //创建SQLContext对象
        SQLContext sqlContext = new SQLContext(sc.sc());
        //注册udf函数
        sqlContext.udf().register("getJsonData",new GetJsonDataUDF(), DataTypes.StringType);

        //构建临时数据
        List<String> userList = new ArrayList<String>();
        userList.add("001 {'username':'tom','age':'12','sex':'男'}");
        userList.add("002 {'username':'henry','age':'18','sex':'男'}");
        userList.add("003 {'username':'jack','age':'32','sex':'男'}");

        JavaRDD<String> rdd = sc.parallelize(userList);
        //将原始数据转化为格式:<id,userInfo>的形式
       JavaRDD<Row> userRDD = rdd.map(
               new Function<String, Row>() {
                   @Override
                   public Row call(String s) throws Exception {
                       //切分数据
                       String[] datas = s.split(" ");
                       String id = datas[0];
                       String userInfo = datas[1];
                       return RowFactory.create(id,userInfo);
                   }
               }
       );
       //注册临时表
       List<StructField> fields = new ArrayList<StructField>();
       fields.add(DataTypes.createStructField("id",DataTypes.StringType,true));
       fields.add(DataTypes.createStructField("userInfo",DataTypes.StringType,true));
       StructType schema = DataTypes.createStructType(fields);
       DataFrame dataFrame = sqlContext.createDataFrame(userRDD, schema);

       dataFrame.registerTempTable("tmp_user");

        //定义sql
        String sql = "SELECT id,"
                +"getJsonData(userInfo,'username')"
                +"FROM tmp_user";
        //开始查询
        DataFrame res = sqlContext.sql(sql);
        res.show();
        sc.stop();
    }
}


 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bokzmm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值