ClickHouse Java多参UDF

news/2024/10/23 9:24:31/

一、环境版本

环境版本
docker clickhouse22.3.10.22
docker pull clickhouse/clickhouse-server:22.3.10.22

二、XML配置

2.1 配置文件

# 创建udf配置文件
vim /etc/clickhouse-server/demo_function.xml
<functions><function><type>executable</type><!--udf函数名称--><name>demo_clickhouse_udf</name><!--返回值类型--><return_type>String</return_type><!--返回值名称,默认值为result--><!--当format为JSONEachRow时,取返回json中的result字段--><return_name>result</return_name><!--输入参数--><!--当format为JSONEachRow时,入参为{"argument_1": 入参1,"argument_2": 入参2}--><argument><type>UInt64</type><name>argument_1</name></argument><argument><type>UInt64</type><name>argument_2</name></argument><!--input和output的数据格式化方式--><format>JSONEachRow</format><!--command运行方式,0为指定命令,1为默认方式--><execute_direct>0</execute_direct><!--command命令,最好带上根目录,避免出现函数不支持问题--><command>/usr/bin/java -jar /var/lib/clickhouse/user_scripts/demo_clickhouse_udf-1.0-SNAPSHOT-jar-with-dependencies.jar</command></function>
</functions>

三、Java代码

新建Maven项目

3.1 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>demo_clickhouse_udf</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.10.1</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artifactId><version>3.3.0</version><configuration><archive><manifest><mainClass>org.example.Main</mainClass></manifest></archive><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs></configuration><executions><execution><id>assemble-all</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin></plugins></build>
</project>

3.2 Main.java

package org.example;import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.annotations.Expose;
import java.io.BufferedInputStream;
import java.io.DataInputStream;public class Main {public static void main(String[] args) {try {DataInputStream in = new DataInputStream(new BufferedInputStream(System.in));String s;// 逐行读取数据while ((s = in.readLine()).length() != 0) {// 获取输入参数Gson gson = new Gson();JsonElement jsonElement = gson.fromJson(s, JsonElement.class);JsonObject jsonObject = jsonElement.getAsJsonObject();String argument_1 = jsonObject.get("argument_1").getAsString();String argument_2 = jsonObject.get("argument_2").getAsString();// 封装输出结果String resultStr = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create().toJson(new Demo(argument_1, argument_2));System.out.println(gson.toJson(new Result(resultStr)));}System.out.flush();} catch (Exception e) {e.printStackTrace();}}/*** 返回对象*/public static class Demo{@Exposeprivate String param1;@Exposeprivate String param2;public Demo(String param1, String param2){this.param1 = param1;this.param2 = param2;}public String getParam1() {return param1;}public void setParam1(String param1) {this.param1 = param1;}public String getParam2() {return param2;}public void setParam2(String param2) {this.param2 = param2;}}/*** 返回结果* 返回值名称必须跟xml文件中的return_name一致* xml文件return_name默认值result* 即: 返回结果为 "{'result': {...}, 'other': {...}, ...}"时* 返回值ClickHouse调用函数返回值只去result的值*/public static class Result {private String result;public String getResult() {return result;}public void setResult(String result) {this.result = result;}public Result(String result){this.result = result;}}
}

3.3 打包将jar包复制到ClickHouse中

docker cp 路径/demo_clickhouse_udf-1.0-SNAPSHOT-jar-with-dependencies.jar 容器id:/var/lib/clickhouse/user_scripts/demo_clickhouse_udf-1.0-SNAPSHOT-jar-with-dependencies.jar

3.4 SQL验证

SYSTEM RELOAD FUNCTIONS; # 刷新函数
SELECT * FROM system.functions WHERE name = 'demo_clickhouse_udf'; # 查询刚添加的udf函数
select demo_clickhouse_udf(1,2)

返回

{"param1":"1","param2":"2"}

3.5 Json字典,数据展开

返回

{"param1":"1","param2":"2"}

数据展开

selectJSON_VALUE(result, '$.param1') as param1,JSON_VALUE(result, '$.param2') as param2
from(select demo_clickhouse_udf(1,2) as result
) t1;

3.6 Json数组,数据展开

java例程

	public static void main(String[] args) {try {DataInputStream in = new DataInputStream(new BufferedInputStream(System.in));String s;// 逐行读取数据while ((s = in.readLine()).length() != 0) {// 获取输入参数Gson gson = new Gson();JsonElement jsonElement = gson.fromJson(s, JsonElement.class);JsonObject jsonObject = jsonElement.getAsJsonObject();String argument_1 = jsonObject.get("argument_1").getAsString();String argument_2 = jsonObject.get("argument_2").getAsString();List<Demo> demoList = new ArrayList<>();demoList.add(new Demo(argument_1, argument_2));demoList.add(new Demo("3", "4"));demoList.add(new Demo("5", "6"));// 封装输出结果String resultStr = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create().toJson(demoList);System.out.println(gson.toJson(new Result(resultStr)));}System.out.flush();} catch (Exception e) {e.printStackTrace();}}

返回

[{"param1":"1","param2":"2"},{"param1":"3","param2":"4"},{"param1":"5","param2":"6"}]

数据展开

selectJSONExtractString(arrayElement, 'param1') as param1,JSONExtractString(arrayElement, 'param2') as param2
from(select demo_clickhouse_udf(1,2) as result
) t1
ARRAY JOIN JSONExtractArrayRaw(result) AS arrayElement;

四、异常问题

4.1 UNKNOWN_FUNCTION

xml文件名称需以function.xml结尾,其它则会添加失败,找不到函数。

# 运行sql
SYSTEM RELOAD FUNCTIONS; # 刷新函数
SELECT * FROM system.functions WHERE name = 'demo_clickhouse_udf'; # 查询刚添加的udf函数
# 报错
Code: 46. DB::Exception: Unknown function demo_clickhouse_udf: While processing demo_clickhouse_udf(1, 2). (UNKNOWN_FUNCTION) (version 22.3.10.22 (official build))

4.2 UNSUPPORTED_METHOD

1.execute_direct需为0

<execute_direct>0</execute_direct>

2.command需带上根目录,如/usr/bin/java

<command>/usr/bin/java -jar /var/lib/clickhouse/user_scripts/demo_clickhouse_udf-1.0-SNAPSHOT-jar-with-dependencies.jar</command>

3.没有安装java等语言环境

4.没有命令或脚本权限

5.版本不支持,如:22.2.3.5

# 报错
Code: 1. DB::Exception: Executable file /usr/bin/java does not exist inside user scripts folder /var/lib/clickhouse/user_scripts/: While processing demo_clickhouse_udf(1, 2). (UNSUPPORTED_METHOD) (version 22.3.10.22 (official build))

4.3 CANNOT_PARSE_QUOTED_STRING

返回字符串格式不对,没有用result封装成json

// 错误的java示例
System.out.println("{'result':1}");
# 报错
Code: 26. DB::ParsingException: Cannot parse JSON string: expected opening quote: While executing ParallelParsingBlockInputFormat: While executing ShellCommandSource: While processing demo_clickhouse_udf(1, 2): (at row 1) . (CANNOT_PARSE_QUOTED_STRING) (version 22.3.10.22 (official build))

五、参考借鉴

ClickHouse Doc
Github Issues


http://www.ppmy.cn/news/1191668.html

相关文章

华为OD机考算法题:阿里巴巴找黄金宝箱(V)

题目部分 题目阿里巴巴找黄金宝箱&#xff08;V&#xff09;难度易题目说明一贫如洗的樵夫阿里巴巴在去砍柴的路上&#xff0c;无意中发现了强盗集团的藏宝地&#xff0c;藏宝地有编号从0-N的箱子&#xff0c;每个箱子上面贴有一个数字。 阿里巴巴念出一个咒语数字 k ( k<N…

关于pytorch张量维度转换及张量运算

关于pytorch张量维度转换大全 1 tensor.view()2 tensor.reshape()3 tensor.squeeze()和tensor.unsqueeze()3.1 tensor.squeeze() 降维3.2 tensor.unsqueeze(idx)升维 4 tensor.permute()5 torch.cat([a,b],dim)6 torch.stack()7 torch.chunk()和torch.split()8 与tensor相乘运算…

08-Docker-网络管理

Docker 在网络管理这块提供了多种的网络选择方式&#xff0c;他们分别是桥接网络、主机网络、覆盖网络、MACLAN 网络、无桥接网络、自定义网络。 1-无桥接网络&#xff08;None Network&#xff09; 当使用无桥接网络时&#xff0c;容器不会分配 IP 地址&#xff0c;也不会连…

Linux纯C串口开发

为什么要用纯C语言 为了数据流动加速&#xff0c;实现低配CPU建立高速数据流而不用CPU干预&#xff0c;避免串口数据流多次反复上升到软件应用层又下降低到硬件协议层。 关于termios.h 麻烦的是&#xff0c;在 Linux 中使用串口并不是一件最简单的事情。在处理 termios.h 标头…

Go 内存逃逸

内存逃逸&#xff08;memory escape&#xff09;是指在编写 Go 代码时&#xff0c;某些变量或数据的生命周期超出了其原始作用域的情况。当变量逃逸到函数外部或持续存在于堆上时&#xff0c;会导致内存分配的开销&#xff0c;从而对程序的性能产生负面影响。Go 编译器会进行逃…

Visual Studio Code 常用快捷键大全

Visual Studio Code 常用快捷键大全 快捷键是编码过程中经常使用&#xff0c;且能够极大提升效率的部分&#xff0c;这里给大家介绍一些VS Code中非常有用的快捷键。 打开和关闭侧边栏 Mac — Command B Windows — Ctrl B Ubuntu — Ctrl B 选择单词 Mac — Command D …

K8S运维 解决openjdk:8-jdk-alpine镜像时区和字体问题

目录 一、问题 二、解决 三、完整代码 一、问题 由于项目的Dockerfile中使用openjdk:8-jdk-alpine作为基础镜像来部署服务&#xff0c;此镜像存在一定问题&#xff0c;例如时差8小时问题&#xff0c;或是由于字体问题导致导出excel文件&#xff0c;图片处理内容为空等。 二…

Web3时代:探索DAO的未来之路

Web3 的兴起不仅代表着技术进步&#xff0c;更是对人类协作、创新和价值塑造方式的一次重大思考。在 Web3 时代&#xff0c;社区不再仅仅是共同兴趣的聚集点&#xff0c;而变成了一个价值交流和创新的平台。 去中心化&#xff1a;超越技术的革命 去中心化不仅仅是 Web3 的技术…