数仓之hive自定义UDTF函数详解

news2024/11/25 20:24:45

学习目录

  • 一、自定义UDTF函数

一、自定义UDTF函数

1.说明文档

A custom UDTF can be created by extending the GenericUDTF abstract class and then implementing the initialize, process, and possibly close methods. The initialize method is called by Hive to notify the UDTF the argument types to expect. The UDTF must then return an object inspector corresponding to the row objects that the UDTF will generate. Once initialize() has been called, Hive will give rows to the UDTF using the process() method. While in process(), the UDTF can produce and forward rows to other operators by calling forward(). Lastly, Hive will call the close() method when all the rows have passed to the UDTF.

读懂文档 首先我们需要知道object inspector和operators的基本概念

(1)operators

operators:即hive中的一条sql语句会被抽象为一个operators,一个operators由一些列的operator组成

operator:为一个特定的操作,完成整个数据处理的过程中的一个功能,类似于spark中的RDD算子,常见的operator有(select operator 用于选择字段、filter operator 用于过滤、join operator 用来做join操作的、group by 用来做分组操作的)

(2)object inspector

object inspector 对象检察器

  1. hive会将一条sql抽象为一个operators,即一些列operator;
  2. 数据会按照计划依次历经每个operator的处理;
  3. 数据在前后两个operator中间传递时,数据和类型是分离的,数据会保存在Java中的object对象当中,而数据的类型会被保存在object inspector 对象检察器中,object inspector还提供了用以解析Java object对象当中所保存数据的方法

文档说明

一个自定义的UDTF函数需要继承GenericUDTF抽象类,且实现initialize(), process(),close()(可选)方法。initialize()方法会被hive调用去通知UDTF函数将要接收到的参数类型。该UDTF必须返回一个与UDTF函数输出相对应的对象检查器。一旦initialize()方法被调用,hive将通过process()方法把一行行数据传给UDTF。在process()方法中,UDTF可以通过调用forward()方法将数据传给其他的operator。最后,当把所有的数据都处理完以后hive会调用close()方法。

initialize方法会被hive调用去通知UDTF函数将要接收到的参数类型

说明:其实就是hive调用initialize方法,把上一个operator返回的对象检查器 传给UDTF,因为object inspector 对象检查器中保存了数据的类型

UDTF必须返回一个与UDTF函数输出相对应的对象检查器

说明:主要目的是为了通知下一个operator即将接收到的数据类型

在process()方法中

说明:在process()方法中按照自己的逻辑,比如: 分离数据,将数据将一行分离多行,分离之后 再通过调用forward()方法将一行一行的数据传递给其他的operator

2.案例说明

接收的是一个json数组字符串,将数组的中每个json元素作为一行输出,具体如图所示
在这里插入图片描述
代码依赖

maven中添加hive依赖

    <dependencies>
        <!--添加hive依赖-->
        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-exec</artifactId>
            <version>3.1.2</version>
        </dependency>
    </dependencies>

代码

import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils;
import org.json.JSONArray;

import java.util.ArrayList;

/**
 * @author wangbo
 * @version 1.0
 */

public class ExplodeJSONArray extends GenericUDTF {

    private PrimitiveObjectInspector inputOI;

    @Override
    public void close() throws HiveException {

    }

    /*
    解释说明:
    该方法两个功能:
    ①hive会通过initialize方法通知UDTF函数接收到的数据类型,通过上一个operator传进来的对象检查器argOIs这个参数获取
    ②该方法返回一个对象检查器,通知下一个operator即将接收到的数据类型

    输入参数类型:
    ObjectInspector[]是一个对象检查器数组,其实就是上一个operator输出结果的对象检查器
    说明:由于UDTF函数可能接收多个参数,所以为对象检查器数组,数组中的元素分别对应输入进来的参数
    功能:
    ①可以通过传进来的对象检查器,校验UDTF函数输入参数的合法性,比如 输入参数的个数、类型等
    ②可以通过传进来的对象检查器,解析上一个operator传递过来的数据。但解析数据主要是在process方法中处理的

    返回值类型:
    StructObjectInspector是一个结构体对象检查器
    说明:由于UDTF函数输出可能有多列,每一列对应着列名和类型,这个中数据结构对应着hive中的Struct结构体
     */

    @Override
    public StructObjectInspector initialize(ObjectInspector[] argOIs) throws UDFArgumentException {

        /**
         * 校验参数
         */
        //通过argOIs数组的长度校验参数的个数,因为数组的每个元素正好对应函数的每个参数
        //(1)校验接收参数的个数
        if(argOIs.length != 1){
            throw new UDFArgumentException("explode_json_array函数只能接收1个参数");
        }

        //获取参数的对象检查器
        ObjectInspector argOI = argOIs[0];

        //(2)校验参数的类型,目标类型为String类型
        //1.判断是否为基本数据类型,argOI.getCategory()获取参数的数据类型
        if (argOI.getCategory() == ObjectInspector.Category.PRIMITIVE){
            throw new UDFArgumentException("explode_json_array函数只能接收基本数据类型");
        }
        //2.判断是基本数据类型,将其强转为String数据类型
        PrimitiveObjectInspector primitiveOI = (PrimitiveObjectInspector) argOI;
        if (primitiveOI.getPrimitiveCategory() != PrimitiveObjectInspector.PrimitiveCategory.STRING){
            throw new UDFArgumentException("explode_json_array函数只能接收String数据类型");
        }


        inputOI = primitiveOI;


        /**
         * initialize方法返回值是StructObjectInspector结构体对象检查器,所以需要构建一个结构体对象检查器
         * 结构体中包含UDTF函数输出的每一列的信息 列名、类型等
         */
        ArrayList<String> fieldNames = new ArrayList<String>();
        ArrayList<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();

        fieldNames.add("col1");     //因为只有一列多有只需要添加一个列名
        //PrimitiveObjectInspectorFactory是基本数据类型的工厂类
        fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);    //该列的数据类型为String类型

        //获取标准的结构体对象检查器,ObjectInspectorFactory是对象检查器的工厂类
        //该工厂类需要传两个ArrayList集合,
        //由于结构体是多列,第一个集合存放各个字段的列名
        //每个字段都有自己类型,第二个集合存放各个列的数据类型
        return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames,
                fieldOIs);
    }


    /**
     *
     * @param args
     * @throws HiveException
     * 前面提到过,两个operator之间传递数据时,数据和类型是分离的,数据保存在Object对象中,数据类型保存在ObjectInspector对象中
     * 这里Object[] args为什么是数组,因为接收的参数可能是多个,而本次参数只有一个
     */
    @Override
    public void process(Object[] args) throws HiveException {
        //因为只有个,所以取第一个元素
        Object arg = args[0];
        //由于我们需要得到String类型的数据,需要将Object转为String类型
        //第一个参数是Object,第二个参数是PrimitiveObjectInspector,
        //说明:传给getString方法Object对象和与之对应的对象检查器,就可以从Object中解析所需要的数据
        String JsonArrayString = PrimitiveObjectInspectorUtils.getString(arg, inputOI);     //这个String就是传进来的 json数组的字符串

        /**
         * 然后需要解析JsonArrayString,需要遍历数组中的每个元素,然后每个元素当作一行forward()出去
         */

        //遍历则需要将上面的字符串解析为JSONArray数组,使用hive当中的json的解析工具类
        JSONArray jsonArray = new JSONArray(JsonArrayString);

        //遍历jsonArray,通过forward将数组元素发出
        for (int i = 0; i < jsonArray.length(); i++) {
            //jsonArray.getString(i)获取一个一个的json对象,只不过这个json对象放在了字符串中
            String string = jsonArray.getString(i);

            /**
             * 注意:这里不能直接将string传入进去,因为任何一个operator输出的数据和输出的对象检查器必须得是一致才行
             * 因为initialize方法输出的是StructObjectInspector结构体对象检查器,一个结构体中会有多列,每一列的数据可能会有一个值或多个值
             * 所以装数据的时候需要用一个数组或者集合去装,即便结构体中只有一列也需要使用数组去装
             */
            String[] result = {string};
            forward(result);
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/48455.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全局JSON序列化导致prometheus数据格式错乱

现象 现场配置完prometheus端点后&#xff0c;返回数据格式乱了&#xff0c;如下图所示 正常结果数据如下图所示 分析 在单个微服务上访问prometheus端点数据返回格式正常。在小型化化格式返回就错乱了。数据返回格式是由消息转化统一处理的。在小型化工程中&#xff0c;…

有限责任公司股东出资的方式有哪几种

一、有限责任公司股东出资的方式有哪几种 有限责任公司股东出资的方式有以下两种&#xff1a; 1.货币出资方式。股东以货币出资的&#xff0c;应当将货币出资足额存入公司在银行开设的账户&#xff1b; 2.非货币财产作价出资方式。以非货币财产出资的&#xff0c;应当依法办…

Web3中文|连年亏损下,web3能拯救B站吗?

作者 | XiaoZiNFTnews.com 11月15日&#xff0c;百度旗下DuDu Lab发行的DuDu Bear NFT已完成铸造&#xff0c;NFT搭建于以太坊上&#xff0c;铸造价格为0.02ETH&#xff0c;发售价格为0.05ETH&#xff0c;共发行1万个&#xff0c;总价值约为455万人民币&#xff0c;目前已售罄…

【JavaScript对象】

JavaScript对象1 本节目标2 对象2.1 什么是对象2.2 为什么需要对象3 创建对象的三种方式3.1 利用字面量创建对象3.2 利用new Object创建对象3.3 利用构造函数创建对象3.4 变量、属性、函数、方法总结3.5 构造函数和对象4 new关键字5 遍历对象属性1 本节目标 说出为什么需要对象…

[附源码]计算机毕业设计JAVA小区物业管理系统论文

[附源码]计算机毕业设计JAVA小区物业管理系统论文 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM my…

Qt编写视频监控系统67-录像计划(支持64通道7*24录像设置)

一、前言 录像计划这个功能一直挂了很久&#xff0c;之前做的也都有保存视频文件功能&#xff0c;其中还分了三大种&#xff0c;第一种是手动开启和停止录像&#xff1b;第二种是按照指定时长比如10s保存文件&#xff1b;第三种是定时30分钟一个文件一直保存。这三种功能直接写…

转铁蛋白修饰的去氢骆驼蓬碱磁纳米脂质体TF-HM-MPS

转铁蛋白又名运铁蛋白&#xff08;Transferrin&#xff0c;TRF、Tf&#xff09;&#xff0c;负责运载由消化管吸收的铁和由红细胞降解释放的铁。以三价铁复合物&#xff08;Tf-Fe3&#xff09;的形式进入骨髓中&#xff0c;供成熟红细胞的生成。转铁蛋白主要存在于血浆中&#…

Kafka牛逼在哪里?

一、Kafka存在哪些方面的优势 1. 多生产者 可以无缝地支持多个生产者&#xff0c;不管客户端在使用单个主题还是多个主题。 2. 多消费者 支持多个消费者从一个单独的消息流上读取数据&#xff0c;而且消费者之间互不影响。 3. 基于磁盘的数据存储 支持消费者非实时地读取…

易基因|DNA甲基化揭示应激反应影响婴儿免疫相关基因的表观遗传调控机制 | 表观发育

易基因&#xff5c;DNA甲基化揭示应激反应影响婴儿免疫相关基因的表观遗传调控机制 | 表观发育 大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 2021年&#xff0c;《Brain, Behavior, and Immunity》杂志发表题为“Biobehavioral org…

3-FreeRTOS任务和协程

概述 “任务”的特征 简单来说&#xff0c;FreeRTOS实时系统能够创建多个独立的任务&#xff0c;任务之间互不干扰。任务创建之后并不是一起运行的&#xff0c;而是通过优先级顺序进行任务的调用&#xff0c;和调度也没有依赖关系。所以不管什么时候程序只能执行一个任务&…

MBA管理类联考英语二题型答题时间及次序问题

还有不到一个月时间&#xff0c;2023年MBA联考也进入到最后的收官阶段&#xff0c;这个阶段对于多数已经系统复习过的考生&#xff0c;一般需要进行通盘梳理备考&#xff0c;而不是专注于单个模块的复习。在做试卷或真题的过程中&#xff0c;如何才能更有利于分数这个问题需要大…

[附源码]Python计算机毕业设计Django电影院网上售票系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Mysql:sql去重的几种方式(大数据hive也可参考)

文章目录前言准备创建表测试数据目标探索distinct 去重group by 去重实现方案方案一方案二方案三前言 我们做数据分析的时候经常会遇到去重问题&#xff0c;下面总结 sql 去重的几种方式&#xff0c;后续如果还有再补充&#xff0c;大数据分析层面包括 hive、clickhouse 也可参…

TStor OneCOS 技术专栏——轻松单桶万亿

TStor OneCOS简介 TStor OneCOS海量对象存储&#xff08;后面简称OneCOS&#xff09;&#xff0c;是基于腾讯云公有云存储架构打造的完全自研的分布式软件定义存储&#xff0c;轻松支持单桶万亿对象和EB级容量&#xff0c;集群容量无限伸缩&#xff0c;同时支持高密大盘等多种…

【个人记录 | UNet | 整理ing】

【代码】 麋鹿 读后感&#xff1a; V1讲框架流程、V2V3狠真实,日常各种报错|预处理|size|格式|维度&#xff1b;“又出错了 狠棒狠棒 T T” 看V1脑袋有个框架&#xff0c;后面两个有较多设计预处理等报错.注意num_classes和weight_path V1&#xff08;视频教程&#xff09;、…

标记二肽Dansyl-Ala-Arg、87687-46-5

二肽Dansyl-Ala-Arg 编号&#xff1a;200087 CAS号&#xff1a;87687-46-5 三字母&#xff1a;Dansyl-Ala-Arg-COOH 描 述&#xff1a;羧肽酶 M 的荧光底物。由于底物和裂解产物 Dansyl-Ala-OH 具有同等荧光&#xff08;λex 340 nm&#xff1b;λem 495 nm&#xff09;&…

PyQt5安装详细教程

先展示一下安装好后的效果如下&#xff1a; 一、安装PyQt5 1、通过使用豆瓣镜像在命令提示符 (WINR)里输入cmd打开窗口进行安装&#xff1a; 点击确定后 输入pip install PyQt5 -i https://pypi.douban.com/simple&#xff0c;等待安装 当下载界面出现Successfully&#xff08…

[附源码]计算机毕业设计springboot良辰之境影视评鉴系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

小红书数据分析工具 | 新中式内容营销怎么做?

一句周杰伦的“国风就是最diao的”&#xff0c;让许多博主纵身涌入一片创作之海&#xff0c;吹起了暗藏在每一个中国人民心底的中国之风。新中式作为一直新锐队伍&#xff0c;发展潜力仍然很大&#xff0c;由于新中式风格所喜爱的人群是特定的&#xff0c;新中式服饰如何在小红…

吉时利2600A系列/2611A数字源表

2600A系列数字源表 吉时利最新的I-V源-测量仪器&#xff0c;既可以用作桌面级I-V特性分析工具&#xff0c;也可以成为多通道I-V测试系统的组 成部分。对于桌面级的应用&#xff0c;2600A系列提供一款嵌入式TSP Express测试软件&#xff0c;允许用户快速、方便地进行常 用的I-V测…