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 {
}
}