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