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();
    }

}

猜你喜欢

转载自blog.csdn.net/ytp552200ytp/article/details/86568853