pig教程 https://www.w3cschool.cn/apache_pig/
Apache Pig 用戶定義函數(UDF)
原文:https://www.w3cschool.cn/apache_pig/apache_pig_user_defined_functions.html,略有改動
除了內置函數之外,Apache Pig還爲 User Defined Function(UDF:用戶定義函數)提供廣泛的支持。使用這些UDF,可以定義我們自己的函數並使用它們。UDF支持六種編程語言,即Java,Jython,Python,JavaScript,Ruby和Groovy。
對於編寫UDF,在Java中提供全面的支持,並在所有其他語言中提供有限的支持。使用Java,你可以編寫涉及處理的所有部分的UDF,如數據加載/存儲,列轉換和聚合。由於Apache Pig是用Java編寫的,因此與其他語言相比,使用Java語言編寫的UDF工作效率更高。
在Apache Pig中,我們還有一個用於UDF名爲 Piggybank 的Java存儲庫。使用Piggybank,我們可以訪問由其他用戶編寫的Java UDF,並貢獻我們自己的UDF。
Java中的UDF的類型
在使用Java編寫UDF時,我們可以創建和使用以下三種類型的函數
-
Filter函數 - Filter(過濾)函數用作過濾器語句中的條件。這些函數接受Pig值作爲輸入並返回布爾值。
-
Eval函數 - Eval函數在FOREACH-GENERATE語句中使用。這些函數接受Pig值作爲輸入並返回Pig結果。
-
Algebraic函數 - Algebraic(代數)函數對FOREACHGENERATE語句中的內包起作用。這些函數用於對內包執行完全MapReduce操作。
使用Java編寫UDF
要使用Java編寫UDF,我們必須集成jar文件 Pig-0.15.0.jar 。在本章節中,將討論如何使用Eclipse編寫示例UDF。在繼續學習前,請確保你已在系統中安裝了Eclipse和Maven。
按照下面給出的步驟寫一個UDF函數:
-
打開Eclipse並創建一個新項目(例如 myproject )。
-
將新創建的項目轉換爲Maven項目。
-
在pom.xml中複製以下內容。此文件包含Apache Pig和Hadoop-core jar文件的Maven依賴關係。
<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.0http://maven.apache .org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Pig_Udf</groupId>
<artifactId>Pig_Udf</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.pig</groupId>
<artifactId>pig</artifactId>
<version>0.15.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-core</artifactId>
<version>0.20.2</version>
</dependency>
</dependencies>
</project>
-
保存文件並刷新它。在 Maven依賴關係部分中,可以找到下載的jar文件。
-
創建名爲 Sample_Eval 的新的類文件,並在其中複製以下內容。
import java.io.IOException;
import org.apache.pig.EvalFunc;
import org.apache.pig.data.Tuple;
import java.io.IOException;
import org.apache.pig.EvalFunc;
import org.apache.pig.data.Tuple;
public class Sample_Eval extends EvalFunc<String>{
public String exec(Tuple input) throws IOException {
if (input == null || input.size() == 0)
return null;
String str = (String)input.get(0);
return str.toUpperCase();
}
}
在編寫UDF時,必須繼承EvalFunc類並向 exec() 函數提供實現。在此函數中,寫入UDF所需的代碼。在上面的例子中,我們返回了將給定列的內容轉換爲大寫的代碼。
-
編譯完類並確認沒有錯誤後,右鍵單擊Sample_Eval.java文件。它將呈現一個菜單。選擇“export”,如以下屏幕截圖所示。
-
注意:打的jar包不需要依賴包
-
點擊“export”,將看到以下窗口。 點擊“JAR file”。
-
點擊“Next>”按鈕繼續操作。將獲得另一個窗口,你需要在本地文件系統中輸入路徑,在其中存儲jar文件。
-
最後,單擊“Finish”按鈕。在指定的文件夾中,創建一個Jar文件 sample_udf.jar 。此jar文件包含用Java編寫的UDF。
使用UDF
在編寫UDF和生成Jar文件後,請按照下面給出的步驟:
步驟1:註冊Jar文件
在寫入UDF(在Java中)後,我們必須使用Register運算符註冊包含UDF的Jar文件。通過註冊Jar文件,用戶可以將UDF的位置綁定到Apache Pig。
語法
下面給出了Register運算符的語法。
注意:此處如果path不寫hdfs://,默認爲本地磁盤路徑,如需hdfs上的文件,請使用hdfs://
每次進入pig,都需要重新REGISTER
REGISTER path;
例
讓我們註冊本章前面創建的sample_udf.jar。以本地模式啓動Apache Pig並註冊jar文件sample_udf.jar,如下所示。
$cd PIG_HOME/bin
$./pig –x local
REGISTER '/$PIG_HOME/sample_udf.jar'
注意:假設路徑中的Jar文件:/$PIG_HOME/sample_udf.jar
步驟2:定義別名
註冊UDF後,可以使用 Define 運算符爲其定義一個別名。
語法
下面給出了Define運算符的語法。
DEFINE alias {function | [`command` [input] [output] [ship] [cache] [stderr] ] };
例
定義sample_eval的別名,如下所示。
DEFINE sample_eval Sample_Eval();
注意此處 如果類中帶包名,如com.test.Sample_Eval; 則需要
DEFINE sample_eval com.test.Sample_Eval();
步驟3:使用UDF
定義別名後,可以使用與內置函數相同的UDF。假設在HDFS /Pig_Data/ 目錄中有一個名爲emp_data的文件,其中包含以下內容。
001,Robin,22,newyork
002,BOB,23,Kolkata
003,Maya,23,Tokyo
004,Sara,25,London
005,David,23,Bhuwaneshwar
006,Maggy,22,Chennai
007,Robert,22,newyork
008,Syam,23,Kolkata
009,Mary,25,Tokyo
010,Saran,25,London
011,Stacy,25,Bhuwaneshwar
012,Kelly,22,Chennai
並假設我們已將此文件加載到Pig中,如下所示。
grunt> emp_data = LOAD 'hdfs://localhost:9000/pig_data/emp1.txt' USING PigStorage(',')
as (id:int, name:chararray, age:int, city:chararray);
現在使用UDF sample_eval 將員工的姓名轉換爲大寫。
grunt> Upper_case = FOREACH emp_data GENERATE sample_eval(name);
也可以直接使用帶有包名的如:
grunt> Upper_case = FOREACH emp_data GENERATE com.test.sample_eval(name);
請驗證關係 Upper_case 的內容,如下所示。
grunt> Dump Upper_case;
(ROBIN)
(BOB)
(MAYA)
(SARA)
(DAVID)
(MAGGY)
(ROBERT)
(SYAM)
(MARY)
(SARAN)
(STACY)
(KELLY)