如何开发presto 自定义UDF函数

作为一个新手菜鸟,在对presto 函数进行开发的时候遇到了很多很多的问题,虽然花费了很多的时间,但最后还是成功的开发了出来UDF函数。

相信很多人都看过一篇《如何开发 Presto 自定义函数(UDF) 》的文章,其实那篇文章讲的很好,但是其中有一些细节并没有写出来,可能对一部分人来说,在开发过程中存在问题。现在分享一下我开发的过程,希望可以帮助到大家。


步骤:

1、创建maven工程

2、修改pom文件

    pom文件可以参考链接:https://blog.csdn.net/szd_8482/article/details/80392796

    (注:上面链接是我自己的pom文件,仅供参考)

    亦或者去GitHub上面参考presto源码中的pom

3、编写UDF函数

    具体参数介绍这里不多说,请参考上方链接,说的已经很详细了

    在这里以聚合函数为例,实现自定义UDF编写

    AVG函数:

import static com.facebook.presto.spi.type.DoubleType.DOUBLE;

import com.facebook.presto.spi.block.BlockBuilder;
import com.facebook.presto.spi.function.AggregationFunction;
import com.facebook.presto.spi.function.AggregationState;
import com.facebook.presto.spi.function.CombineFunction;
import com.facebook.presto.spi.function.InputFunction;
import com.facebook.presto.spi.function.OutputFunction;
import com.facebook.presto.spi.function.SqlType;
import com.facebook.presto.spi.type.StandardTypes;
import com.presto.state.LongAndDoubleState;
import com.presto.utils.PrecisionUtil;

@AggregationFunction("_avg")
public final class AVG{
	private Avg() {
	}

	@InputFunction
	public static void input(@AggregationState LongAndDoubleState state, @SqlType(StandardTypes.BIGINT) long value) {
		state.setLong(state.getLong() + 1);
		state.setDouble(state.getDouble() + value);
	}

	@InputFunction
	public static void input(@AggregationState LongAndDoubleState state, @SqlType(StandardTypes.DOUBLE) double value) {
		state.setLong(state.getLong() + 1);
		state.setDouble(state.getDouble() + value);
	}

	@CombineFunction
	public static void combine(@AggregationState LongAndDoubleState state,
			@AggregationState LongAndDoubleState otherState) {
		state.setLong(state.getLong() + otherState.getLong());
		state.setDouble(state.getDouble() + otherState.getDouble());
	}

	@OutputFunction(StandardTypes.DOUBLE)
	public static void output(@AggregationState LongAndDoubleState state, BlockBuilder out) {
		long count = state.getLong();
		if (count == 0) {
			out.appendNull();
		} else {
			double value = state.getDouble();
			
			double tmp = Double.valueOf(PrecisionUtil.getPrecision(value / count));
			
			DOUBLE.writeDouble(out, tmp);
		}
	}
}

LongAndDoubleState:

import com.facebook.presto.spi.function.AccumulatorState;

public interface LongAndDoubleState extends AccumulatorState{

    
    long getLong();

    void setLong(long value);

    double getDouble();

    void setDouble(double value);

  
}

工具类:精确小数点后位数

import java.text.DecimalFormat;

/**
 * double类型 小数点后保留四位
 * 
 * @author xueqing-dev
 *
 */
public class PrecisionUtil {

	public static double getPrecision(double value) {

		DecimalFormat df = new DecimalFormat("####0.0000");

		double tmp = Double.valueOf(df.format(value));

		return tmp;
	}
}

4、plugin插件注册:

        将UDF函数的逻辑写好之后,需要把相关的类注册到plugin中,才能被presto识别

    

package com.xqy.szd.presto.plugin;

import java.util.Set;

import com.facebook.presto.spi.Plugin;
import com.google.common.collect.ImmutableSet;


public class UDF_Plugin implements Plugin{

	@Override
	public Set<Class<?>> getFunctions(){
		
		return ImmutableSet.<Class<?>>builder()
					.add(AVG.class)
					.build();
	}
}

5、在 src/main/resources/META-INF/services 中新建名为 com.facebook.presto.spi.Plugin 的文本文件,内容就是之前实现 Plugin 接口的类名

    如果没有resources,需要自己建立并且加入source中(右击-->Build Path)


6、package 打包

    函数开发好之后,需要通过maven打包,然后把jar包上传到presto中的plugin中

    maven中 运行package 完成打包过程

    

    打包完成后,需要上传的是后缀为 .zip 的包,这里面包括函数所需要的依赖

7、上传到presto中的plugin中 ,解压

unzip demo-0.0.1-SNAPHOT.zip

8、重启presto

9、查询是否注册

show functions;


至此 我的UDF函数开发过程分享完成,希望对大家有所帮助

猜你喜欢

转载自blog.csdn.net/szd_8482/article/details/80680623