玩轉大數據系列之Apache Pig高級技能之函數編程(六)

原創不易,轉載請務必註明,原創地址,謝謝配合!
http://qindongliang.iteye.com/


Pig系列的學習文檔,希望對大家有用,感謝關注散仙!

Apache Pig的前世今生

Apache Pig如何自定義UDF函數?

Apache Pig5行代碼怎麼實現Hadoop的WordCount?

Apache Pig入門學習文檔(一)

Apache Pig學習筆記(二)

Apache Pig學習筆記之內置函數(三)

玩轉大數據系列之Apache Pig如何與Apache Lucene集成(一)

玩轉大數據系列之Apache Pig如何與Apache Solr集成(二)

玩轉大數據系列之Apache Pig如何與MySQL集成(三)

玩轉大數據系列之如何給Apache Pig自定義存儲形式(四)

玩轉大數據系列之Apache Pig如何通過自定義UDF查詢數據庫(五)

如何使用Pig集成分詞器來統計新聞詞頻?


bdb45a8c-0783-3da4-81ae-cf969e75f38b.png

在Hadoop的生態系統中,如果我們要離線的分析海量的數據,大多數人都會選擇Apache Hive或Apache Pig,在國內總體來說,Hive使用的人羣佔比比較高, 而Pig使用的人相對來說,則少的多,這並不是因爲Pig不成熟,不穩定,而是因爲Hive提供了類數據庫SQL的查詢語句,使得大多人上手Hive非常容易,相反而Pig則提供了類Linux shell的腳本語法,這使得大多數人不喜歡使用。

如果在編程界,統計一下會SQL和會shell,那個人數佔的比重大,散仙覺得,毫無疑問肯定是SQL語句了。因爲有相當一部分編程人員是不使用Linux的,而是微軟的的一套從C#,到ASP.NET,SQL Server再到Windows的專用服務器 。



7c7b3bef-0dda-3ac6-8cdb-1ecc1dd9c194.jpg

OK,扯遠了,趕緊回來,使用shell的攻城師們,我覺得都會愛上它的,因爲在linux系統中,沒有比shell更簡潔易用了,如果再配上awk和sed更是如虎添翼了。

我們都知道shell是支持函數調用的,這一點和JavaScript是非常類似的,通過定義函數我們可以重複使用某個功能,而不用再次大量編碼,其中,把變的東西,分離成參數,不變的東西定義成語句,這樣以來,就能夠降低編碼的冗餘和複雜性,試想一下,如果Java裏,沒有方法,那將會是多麼不可思議的一件事。

Pig作爲類shell的語言,也支持了函數的方式,封裝某個功能,以便於我們重用,這一點相比Hive來說,是一個很好的優勢。

下面先看下定義Pig函數(也叫宏命令)定義的語法:

DEFINE (macros) :
支持的參數:
alias  pig的標量引用
整形(integer)
浮點型(float)
字符串(String)

下面看幾個例子,讓我們迅速對它熟悉並掌握,先看下我們的測試數據:

Java代碼 複製代碼 收藏代碼spinner.gif

  1. 1,張三,男,23,中國   

  2. 2,張三,女,32,法國   

  3. 3,小花,男,20,英國   

  4. 4,小紅,男,16,中國   

  5. 5,小紅,女,25,洛陽   

  6. 6,李靜,女,25,中國河南安陽   

  7. 7,王強,男,11,英國   

  8. 8,張飛,男,20,美國  

1,張三,男,23,中國
2,張三,女,32,法國
3,小花,男,20,英國
4,小紅,男,16,中國
5,小紅,女,25,洛陽
6,李靜,女,25,中國河南安陽
7,王強,男,11,英國
8,張飛,男,20,美國



再看下pig腳本:

Java代碼 複製代碼 收藏代碼spinner.gif

  1. --定義pig函數1 支持分組統計數量   

  2. DEFINE group_and_count (A,group_key,number_reduces) RETURNS B {   

  3.     

  4.  d = group $A by $group_key parallel $number_reduces;   

  5.     

  6.  $B = foreach d generate group, COUNT($1);   

  7.   

  8. };   

  9.   

  10.   

  11. --定義pig函數2 支持排序   

  12. --A 關係引用標量   

  13. --order_field 排序的字段   

  14. --order_type 排序方式 desc ? asc ?   

  15. --storedir 存儲的HDFS路徑   

  16. --空返回值   

  17. define my_order(A,order_field,order_type,storedir) returns void {   

  18.     

  19.   d = order $A by $order_field $order_type ;   

  20.   store  d into '$storedir' ;     

  21.     

  22.   

  23. };    

  24.   

  25.   

  26. --定義pig函數3,支持filter過濾,以及宏命令裏面調用   

  27.   

  28. --定義過濾操作   

  29. define  myfilter (A,field,count) returns B{   

  30.   

  31.    b= filter $A by $field > $count ;   

  32.   

  33.    $B = group_and_count(b,'sex',1);   

  34.   

  35. };   

  36.   

  37.   

  38. a = load  '/tmp/dongliang/318/person' using PigStorage(',') AS (id:int,name:chararray,sex:chararray,age:int,address:chararray) ;   

  39.   

  40.   

  41. --------pig函數1測試-----------------   

  42.   

  43. --定義按名字分組   

  44. --bb = group_and_count(a,name,1);   

  45. --定義按性別分組   

  46. --cc = group_and_count(a,sex,1);   

  47. --dump bb;   

  48. --dump cc;   

  49.   

  50. -------pig函數2測試------------------   

  51.   

  52. --按年齡降序   

  53. --my_order(a,age,'desc','/tmp/dongliang/318/z');   

  54.   

  55.   

  56.   

  57. --dump a;   

  58.   

  59.   

  60. -------pig函數3測試------------------   

  61.   

  62.  --過濾年齡大於20的,並按性別,分組統計數量   

  63.  r =  myfilter(a,'age',20);   

  64.   

  65.   

  66. dump r;  

--定義pig函數1 支持分組統計數量
DEFINE group_and_count (A,group_key,number_reduces) RETURNS B {
 
 d = group $A by $group_key parallel $number_reduces;
 
 $B = foreach d generate group, COUNT($1);

};


--定義pig函數2 支持排序
--A 關係引用標量
--order_field 排序的字段
--order_type 排序方式 desc ? asc ?
--storedir 存儲的HDFS路徑
--空返回值
define my_order(A,order_field,order_type,storedir) returns void {
 
  d = order $A by $order_field $order_type ;
  store  d into '$storedir' ;  
 

}; 


--定義pig函數3,支持filter過濾,以及宏命令裏面調用

--定義過濾操作
define  myfilter (A,field,count) returns B{

   b= filter $A by $field > $count ;

   $B = group_and_count(b,'sex',1);

};


a = load  '/tmp/dongliang/318/person' using PigStorage(',') AS (id:int,name:chararray,sex:chararray,age:int,address:chararray) ;


--------pig函數1測試-----------------

--定義按名字分組
--bb = group_and_count(a,name,1);
--定義按性別分組
--cc = group_and_count(a,sex,1);
--dump bb;
--dump cc;

-------pig函數2測試------------------

--按年齡降序
--my_order(a,age,'desc','/tmp/dongliang/318/z');



--dump a;


-------pig函數3測試------------------

 --過濾年齡大於20的,並按性別,分組統計數量
 r =  myfilter(a,'age',20);


dump r;



在上面的腳本中,散仙定義了三個函數,
(1)分組統計數量
(2)自定義輸出存儲
(3)自定義過濾並結合(1)統計數量

通過這3個例子,讓大家對pig函數有一個初步的認識,上面的函數和代碼都在一個腳本中,這樣看起來不太友好,而且重用性,還沒有得到最大發揮,實際上函數和主體腳本是可以分離的,再用的時候,我們只需要導入函數腳本,即可擁有所有的函數功能,這樣一來,函數腳本被分離到主腳本外面,就大大增加了函數腳本的重用性,我們也可以再其他腳本中引用,而且函數腳本中也可以再次引用其他的函數腳本,但前提是不能夠,遞歸引用,這樣Pig語法在執行時,是會報錯的,下面看下分離後的腳本文件:

一:函數腳本文件

Java代碼 複製代碼 收藏代碼spinner.gif

  1. --定義pig函數1 支持分組統計數量   

  2. --A 關係引用標量   

  3. --group_key 分組字段   

  4. --使用reduce的個數   

  5. --返回最終的引用結果   

  6. DEFINE group_and_count (A,group_key,number_reduces) RETURNS B {   

  7.     

  8.  d = group $A by $group_key parallel $number_reduces;   

  9.     

  10.  $B = foreach d generate group, COUNT($1);   

  11.   

  12. };   

  13.   

  14.   

  15. --定義pig函數2 支持排序   

  16. --A 關係引用標量   

  17. --order_field 排序的字段   

  18. --order_type 排序方式 desc ? asc ?   

  19. --storedir 存儲的HDFS路徑   

  20. --空返回值   

  21. define my_order(A,order_field,order_type,storedir) returns void {   

  22.     

  23.   d = order $A by $order_field $order_type ;   

  24.   store  d into '$storedir' ;     

  25.     

  26.   

  27. };    

  28.   

  29.   

  30. --定義pig函數3,支持filter過濾,以及宏命令裏面調用   

  31. --A 關係引用標量   

  32. --field 過濾的字段   

  33. --count 閾值   

  34. --返回最終的引用結果   

  35.   

  36. define  myfilter (A,field,count) returns B{   

  37.   

  38.    b= filter $A by $field > $count ;   

  39.   

  40.    $B = group_and_count(b,'sex',1);   

  41.   

  42. };   

  43.   

  44.   

  45.   

  46. [search@dnode1 pigmacros]$   

--定義pig函數1 支持分組統計數量
--A 關係引用標量
--group_key 分組字段
--使用reduce的個數
--返回最終的引用結果
DEFINE group_and_count (A,group_key,number_reduces) RETURNS B {
 
 d = group $A by $group_key parallel $number_reduces;
 
 $B = foreach d generate group, COUNT($1);

};


--定義pig函數2 支持排序
--A 關係引用標量
--order_field 排序的字段
--order_type 排序方式 desc ? asc ?
--storedir 存儲的HDFS路徑
--空返回值
define my_order(A,order_field,order_type,storedir) returns void {
 
  d = order $A by $order_field $order_type ;
  store  d into '$storedir' ;  
 

}; 


--定義pig函數3,支持filter過濾,以及宏命令裏面調用
--A 關係引用標量
--field 過濾的字段
--count 閾值
--返回最終的引用結果

define  myfilter (A,field,count) returns B{

   b= filter $A by $field > $count ;

   $B = group_and_count(b,'sex',1);

};



[search@dnode1 pigmacros]$



二,主體腳本文件

Java代碼 複製代碼 收藏代碼spinner.gif

  1. --導入pig公用的函數庫   

  2.   

  3. import 'function.pig' ;   

  4.   

  5. a = load  '/tmp/dongliang/318/person' using PigStorage(',') AS (id:int,name:chararray,sex:chararray,age:int,address:chararray) ;   

  6.   

  7.   

  8. --------pig函數1測試-----------------   

  9.   

  10. --定義按名字分組   

  11. --bb = group_and_count(a,name,1);   

  12. --定義按性別分組   

  13. --cc = group_and_count(a,sex,1);   

  14. --dump bb;   

  15. --dump cc;   

  16.   

  17.   

  18. -------pig函數2測試------------------   

  19.   

  20. --按年齡降序   

  21. --my_order(a,age,'desc','/tmp/dongliang/318/z');   

  22. --dump a;   

  23.   

  24.   

  25. -------pig函數3測試------------------   

  26.   

  27.  --過濾年齡大於20的,並按性別,分組統計數量   

  28.  r =  myfilter(a,'age',20);   

  29.  dump r;  

--導入pig公用的函數庫

import 'function.pig' ;

a = load  '/tmp/dongliang/318/person' using PigStorage(',') AS (id:int,name:chararray,sex:chararray,age:int,address:chararray) ;


--------pig函數1測試-----------------

--定義按名字分組
--bb = group_and_count(a,name,1);
--定義按性別分組
--cc = group_and_count(a,sex,1);
--dump bb;
--dump cc;


-------pig函數2測試------------------

--按年齡降序
--my_order(a,age,'desc','/tmp/dongliang/318/z');
--dump a;


-------pig函數3測試------------------

 --過濾年齡大於20的,並按性別,分組統計數量
 r =  myfilter(a,'age',20);
 dump r;


需要注意的是,導入的函數文件,需要用單引號引起來,這樣我們就完成了pig函數的重用,是不是非常類似shell的語法呢?有興趣的同學們,趕緊體驗一把吧!  


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章