说明:有时候,hive的自定义函数,以及满足不了我们的需求了,那么这时候我们就需要自己写一些函数,来满足我们的业务需求,下面记录一次自定义函数的实现
方法一:
import org.apache.hadoop.hive.ql.exec.UDF;
/**
* 自定义的hiveUDF函数,用于计算两点(经纬度)之间的距离是否超过1KM
*/
public class DistanceCalculate extends UDF {
private static final double EARTH_RADIUS = 6378.137;
private static final double KM = 1.0;
private static double rad(double d) {
return d * Math.PI / 180.0;
}
/**
* @param lat1 点1的纬度
* @param lng1 点1的经度
* @param lat2 点2的纬度
* @param lng2 点2的经度
* @return 返回是否超过1KM
*/
public static boolean evaluate(double lat1, double lng1, double lat2,
double lng2) {
double radLat1 = rad(lat1);
double radLat2 = rad(lat2);
double a = radLat1 - radLat2;
double b = rad(lng1) - rad(lng2);
double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
+ Math.cos(radLat1) * Math.cos(radLat2)
* Math.pow(Math.sin(b / 2), 2)));
s = s * EARTH_RADIUS;
s = Math.round(s * 10000d) / 10000d;
// s = s * 1000;
return s > KM ? true : false;
}
public static void main(String[] args) {
System.out.println(getDistance(26.451032, 99.42388, 22.007468, 100.794432));
}
}
注意,名字一定是evaluate,看一个源码的函数:
你会发现所有的类都有这个evaluate函数,这个函数就是你的自定义函数的输入和输出,所以名字不能错,如果有不同的接收;类型,那么可以参考源码:
方法二:
// 定义
def getCookieLabelScores(cookieLabel: String): Int = {
cookieLabelScoresMapB.value.getOrElse(cookieLabel, 0)
}
// 注册
spark.udf.register("getCookieLabelScores",
(cookieLabel: String) => getCookieLabelScores(cookieLabel))
// 使用
callUDF("getCookieLabelScores", $"字段名")
永久生效:
1.需要源码编译(太麻烦)
2.将jar包上传到hdfs中:
hadoop fs -put ./udf-1.0-SNAPSHOT.jar hdfs://test:9999/user/hive
create function distance_calculate(你的函数名) as "com.jrq.myudf.DistanceCalculate"(jar自定义函数类) using jar "hdfs://test:9999/user/hive/udf-1.0-SNAPSHOT.jar"(hdfs中的位置)
**使用:**
select test.distance_calculate(26.451032, 99.42388, 22.007468, 100.794432);
(test是我在test数据库中执行的上面的语句,如果你在test数据库下执行这个语句,那么就不需要加上test,这也是此种方法第一个弊端,好处就是:加自定义函数的时候,不需要频繁去编译源码,注意jar包一定不能删除,因为hive如果重启后再次使用函数,会自动去加载,删除了就加载不了了)