ハイブ書き込みカスタムUDF関数とUDTF関数

1.ユーザー定義関数UDF

ユーザー定義関数(UDF)は、ユーザーがHiveQLを拡張できるようにする強力な関数です。ユーザーはJavaで独自のUDFを作成できます。ユーザー定義関数がユーザーセッションに追加されると(対話型またはスクリプトによって実行されると)、組み込み関数のように使用され、オンラインヘルプを提供することもできます。Hiveには多くの種類のユーザー定義関数があり、それぞれが入力データに対して特定の「カテゴリ」変換プロセスを実行します。

UDF機能の機能:ライン入力とライン出力。要するに、1つのインと1つのアウト。

パブリックフィールドを解析するUDF関数:

UDFクラスを書く

pom.xmlファイルに次のコンテンツを追加します

<dependency>
        <groupId>org.apache.hive</groupId>
        <artifactId>hive-exec</artifactId>
        <version>${hive.version}</version>
    </dependency>
<dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>${hadoop.version}</version>
        </dependency>

 コード

UDFを作成するには、UDFを継承し、evaluate()関数を実装する必要があります。クエリプロセスでは、このクラスは、クエリ内のこの関数のアプリケーションごとにインスタンス化されます。評価()関数は、入力の各行に対して呼び出されます。Evaluation()によって処理された値は、Hiveに返されます。同時に、ユーザーはevaluateメソッドをオーバーライドできます。Hiveは、Javaメソッドのオーバーロードなどの一致するメソッドを自動的に選択します

package UDF;

import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.json.JSONException;
import org.json.JSONObject;

public class BaseFieidUDF extends UDF {
    public static void main(String[] args) throws JSONException {
        String line = "1583776223469|{\"cm\":{\"ln\":\"-48.5\",\"sv\":\"V2.5.7\",\"os\":\"8.0.9\",\"g\":\"[email protected]\",\"mid\":\"0\",\"nw\":\"4G\",\"l\":\"pt\",\"vc\":\"3\",\"hw\":\"750*1134\",\"ar\":\"MX\",\"uid\":\"0\",\"t\":\"1583707297317\",\"la\":\"-52.9\",\"md\":\"sumsung-18\",\"vn\":\"1.2.4\",\"ba\":\"Sumsung\",\"sr\":\"V\"},\"ap\":\"app\",\"et\":[{\"ett\":\"1583705574227\",\"en\":\"display\",\"kv\":{\"goodsid\":\"0\",\"action\":\"1\",\"extend1\":\"1\",\"place\":\"0\",\"category\":\"63\"}},{\"ett\":\"1583760986259\",\"en\":\"loading\",\"kv\":{\"extend2\":\"\",\"loading_time\":\"4\",\"action\":\"3\",\"extend1\":\"\",\"type\":\"3\",\"type1\":\"\",\"loading_way\":\"1\"}},{\"ett\":\"1583746639124\",\"en\":\"ad\",\"kv\":{\"activityId\":\"1\",\"displayMills\":\"111839\",\"entry\":\"1\",\"action\":\"5\",\"contentType\":\"0\"}},{\"ett\":\"1583758016208\",\"en\":\"notification\",\"kv\":{\"ap_time\":\"1583694079866\",\"action\":\"1\",\"type\":\"3\",\"content\":\"\"}},{\"ett\":\"1583699890760\",\"en\":\"favorites\",\"kv\":{\"course_id\":4,\"id\":0,\"add_time\":\"1583730648134\",\"userid\":7}}]}";

        String mid = new BaseFieidUDF().evaluate(line, "st");

        System.out.println(mid);
    }

    private String evaluate(String line, String key) throws JSONException {

        String[] log = line.split("\\|");

        //对数据合法性验证,这一块比较复杂
        if (log.length != 2 || StringUtils.isBlank(log[1])){
            return "";
        }

        // 如果能走到下面,说明if没有走进去,数据合法,那么就说明切分之后长度为2 而且json数据不为空
        JSONObject baseJson = new JSONObject(log[1].trim());

        String result = "";

        //获取服务器时间 st : server_time  ,mid,l,os
        if ("st".equals(key)) {
            result = log[0].trim();
        }else if ("et".equals(key)){
            //获取事件数组
            if (baseJson.has("et")){
                result = baseJson.getString("et");
            }
        }else {
            // 获取cm:{具体的一个个kv}
            /*
                {"ln":"-106.3","sv":"V2.7.0","os":"8.1.2","g":"[email protected]","mid":"1","nw":"WIFI
                ","l":"es","vc":"8","hw":"1080*1920","ar":"MX","uid":"1","t":"1603997770291","la":"-39.8","md":"sumsung-16"
                ,"vn":"1.3.2","ba":"Sumsung","sr":"B"}
             */
            JSONObject cm = baseJson.getJSONObject("cm");

            //获取key对应公共字段的value,这个key就是公共字段的很多个不同的key值
            if (cm.has(key)){
                result = cm.getString(key);
            }
        }
        return result;
    }
}

2.カスタムUDTF機能

UDTF機能の特徴:マルチトラベルとマルチトラベル。略語、もっと入って、もっと出て

  • 継承org.apache.hadoop.hive.ql.udf.generic。GenericUDTFおよび実装する3つの方法初期化、プロセスと密接に

  • UDTFは最初にinitializeメソッドを呼び出します。このメソッドは、UDTF戻り行情報の太字のスタイル(戻り番号、タイプ)を返します

  • 初期化が完了すると、プロセスメソッドが呼び出されます。実際の処理プロセスはプロセス関数内にあります。プロセスでは、各forward()呼び出しが行を生成します。複数の列が生成される場合、複数の列の値は次のようになります。配列に配置された後、この配列はforward()関数に渡されます。

  • 最後に、close()メソッドが呼び出され、クリーンアップが必要なメソッドがクリーンアップされます。

特定のイベントを分析するUDTF機能

コード

package UDTF;

import org.apache.commons.lang.StringUtils;
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.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.json.JSONArray;
import org.json.JSONException;

import java.util.ArrayList;

public class EventJsonUDTF extends GenericUDTF {
    //该方法中,我们指定输出参数的名称和参数类型
    public StructObjectInspector initialize(StructObjectInspector argOIs)throws UDFArgumentException {
        ArrayList<String> fieldNames = new ArrayList<String>();
        ArrayList<ObjectInspector> fieldOIs = new ArrayList<>();

        fieldNames.add("event_name");
        fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
        fieldNames.add("event_json");
        fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);

        return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames,fieldOIs);

    }

    //输入一条记录,输出若干条结果,多条
    @Override
    public void process(Object[] objects) throws HiveException {
        //获取传入的et [{},{},{},{}]
        // objects[0].toString() ----> [{},{},{},{}]
        String input = objects[0].toString();

        //如果传进来的数据为空,直接返回过滤掉该数据
        if (StringUtils.isBlank(input)){
            return;
        }else {
            try {
                //获取一共有几个事件(ad/facoriters)
                JSONArray ja = new JSONArray(input);

                if (ja == null)
                    return;

                //循环遍历每一个事件
                for (int i = 0;i < ja.length();i++){
                    //遍历出来的没一条数据: {"ett":"1604021380867","en":"display","kv":{"goodsid":"0","action":"2","extend1":"2","place":"4","category":"53"}}
                    String[] result = new String[2];

                    try {
                        //取出每个事件的名称(ad/factoriters)
                        result[0] = ja.getJSONObject(i).getString("en");

                        //取出每一个事件整体
                        result[1] = ja.getString(i);
                    }catch (JSONException e){
                        continue;
                    }
                    //将结果返回
                    forward(result);
                }
            }catch (JSONException e){
                e.printStackTrace();
            }
        }
    }

    //当没有记录处理的时候该方法会被调用,用来清理代码或者产生额外的输出
    @Override
    public void close() throws HiveException {

    }

}

 

おすすめ

転載: blog.csdn.net/Poolweet_/article/details/109453718