当前位置: 首页 > 工具软件 > Apache Pig > 使用案例 >

Apache Pig的一些基础概念及用法总结(3)

连文栋
2023-12-01

(26)错误“ERROR org.apache.pig.tools.grunt.Grunt - ERROR 2042: Error in new logical plan. Try -Dpig.usenewlogicalplan=false.”的可能原因
Pig的bug,详见此链接
其他原因。我遇到并解决了一例。具体的 代码不便在此陈列,但是基本可以说是由于自己写的Pig代码对复杂数据结构的处理不当导致的,后来我尝试更改了一种实现方式,就绕过了这个问题。关于这 点,确实还是要具体问题具体分析的,在这里没有实例的话,无法给大家一个明确的解决问题的指南。

(27)如何在Pig中使用正则表达式对字符串进行匹配
假设你有如下数据文件:

1
2
3
4
5
[root@localhost ~] # cat a.txt
1 http: //ui .qq.com /abcd .html
5 http: //tr .qq.com /743 .html
8 http: //vid .163.com /trees .php
9 http:auto.qq.com /us .php

现在要找出该文件中,第二列符合“*//*.qq.com/*”模式的所有行(此处只有前两行符合条件),怎么做?
Pig代码如下:

1
2
3
A = LOAD 'a.txt' AS (col1: int , col2: chararray);
B = FILTER A BY col2 matches '.*//.*\\.qq\\.com/.*'
DUMP B;

我们看到,matches关键字对 col2 进行了正则匹配,它使用的是Java格式的正则表达式匹配规则。
表示任意字符,表示字符出现任意次数;\. 对 进行了转义,表示匹配 这个字符;就是表示匹配 这个字符。
这里需要注意的是,在引号中,用于转义的字符 需要打两个才能表示一个,所以上面的 \\. 就是与正则中的 \. 是一样的,即匹配 这个字符。所以,如果你要匹配数字的话,应该用这种写法(\d表示匹配数字,在引号中必须用\\d):

1
B = FILTER A BY (col matches '\\d.*' );

文章来源:http://www.codelast.com/
最后输出结果为:

1
2
(1,http://ui.qq.com/abcd.html)
(5,http://tr.qq.com/743.html)

可见结果是正确的。

(28)如何截取一个字符串中的某一段
在处理数据时,如果你想提取出一个日期字符串的年份,例如提取出“2011-10-26”中的“2011”,可以用内置函数 SUBSTRING 来实现:

SUBSTRING

Returns a substring from a given string.

Syntax

SUBSTRING(string, startIndex, stopIndex)

下面举一个例子。假设有数据文件:

1
2
3
4
5
6
[root@localhost ~] # cat a.txt
2010-05-06  abc
2008-06-18  uio
2011-10-11  tyr
2010-12-23  fgh
2011-01-05  vbn

第一列是日期,现在要找出所有不重复的年份有哪些,可以这样做:

1
2
3
4
A = LOAD 'a.txt' AS (dateStr: chararray, flag: chararray);
B = FOREACH A GENERATE SUBSTRING (dateStr, 0, 4);
C = DISTINCT B;
DUMP C;

输出结果为:

1
2
3
(2008)
(2010)
(2011)

可见达到了我们想要的效果。
上面的代码太简单了,不必多言,唯一需要说明一下的是 SUBSTRING 函数,它的第一个参数是要截取的字符串,第二个参数是起始索引(从0开始),第三个参数是结束索引。
文章来源:http://www.codelast.com/
(29)如何拼接两个字符串
假设有以下数据文件:

1
2
3
4
5
[root@localhost ~] # cat 1.txt
abc 123
cde 456
fgh 789
ijk 200

现在要把第一列和第二列作为字符串拼接起来,例如第一行会变成“abc123”,那么使用CONCAT这个求值函数(eval function)就可以做到:

1
2
3
A = LOAD '1.txt' AS (col1: chararray, col2: int );
B = FOREACH A GENERATE CONCAT(col1, (chararray)col2);
DUMP B;

输出结果为:

1
2
3
4
(abc123)
(cde456)
(fgh789)
(ijk200)

注意这里故意在加载数据的时候把第二列指定为int类型,这是为了说明数据类型不一致的时候CONCAT会出错(你可以试验一下):

ERROR org.apache.pig.tools.grunt.Grunt - ERROR 1045: Could not infer the matching function for org.apache.pig.builtin.CONCAT as multiple or none of them fit. Please use an explicit cast.

所以在后面CONCAT的时候,对第二列进行了类型转换。
另外,如果数据文件内容为:

1
2
3
4
5
[root@localhost ~] # cat 1.txt
5 123
7 456
8 789
0 200

那么,如果对两列整数CONCAT:

1
2
A = LOAD '1.txt' AS (col1: int , col2: int );
B = FOREACH A GENERATE CONCAT(col1, col2);

同样也会出错

ERROR org.apache.pig.tools.grunt.Grunt - ERROR 1045: Could not infer the matching function for org.apache.pig.builtin.CONCAT as multiple or none of them fit. Please use an explicit cast.

要注意这一点。
有人可能会问:要拼接几个字符串的话怎么办?CONCAT 套 CONCAT 就要可以了(有点笨,但管用): CONCAT(a, CONCAT(b, c))

(30)如何求两个数据集的重合 & 不同的数据类型JOIN会失败
假设有以下两个数据文件:

1
2
3
4
5
[root@localhost ~] # cat 1.txt
123
456
789
200

以及:

1
2
3
4
[root@localhost ~] # cat 2.txt
200
333
789

现在要找出两个文件中,相同的数据有多少行,怎么做?这也就是所谓的求两个数据集的重合
用关系操作符JOIN,我们可以达到这个目的。在处理海量数据时,经常会有求重合的需求。所以JOIN是Pig中一个极其重要的操作。
在本例中,两个文件中有两个相同的数据行:789以及200,因此,结果应该是2。
我们先来看看正确的代码:

1
2
3
4
5
6
A = LOAD '1.txt' AS (a: int );  
B = LOAD '2.txt' AS (b: int );
C = JOIN A BY a, B BY b;
D = GROUP C ALL ;
E = FOREACH D GENERATE COUNT (C);
DUMP E;

解释一下:
第一、二行是加载数据,不必多言。
第三行按A的第1列、B的第二列进行“结合”,JOIN之后,a、b两列不相同的数据就被剔除掉了。C的数据结构为:

1
C: {A::a: int,B::b: int}

C的数据为:

1
2
(200,200)
(789,789)

由于我们要统计的是数据行数,所以上面的Pig代码中的第4、5行就进行了计数的运算。
如果文件 2.txt 多一行数据“200”,结果会是什么?答案是:结果为3行。这个时候C的数据为:

1
2
3
(200,200)
(200,200)
(789,789)

所以如果你要去除重复的,还需要用DISTINCE对C处理一下:

1
2
3
4
5
6
7
A = LOAD '1.txt' AS (a: int );
B = LOAD '2.txt' AS (b: int );
C = JOIN A BY a, B BY b;
uniq_C = DISTINCT C;
D = GROUP uniq_C ALL ;
E = FOREACH D GENERATE COUNT (uniq_C);
DUMP E;

这样得到的结果就是2了。
文章来源:http://www.codelast.com/
尤其需要注意的是,如果JOIN的两列具有不同的数据类型,是会失败的。例如以下代码:

1
2
3
4
5
6
A = LOAD '1.txt' AS (a: int );  
B = LOAD '2.txt' AS (b: chararray);
C = JOIN A BY a, B BY b;
D = GROUP C ALL ;
E = FOREACH D GENERATE COUNT (C);
DUMP E;

在语法上是没有错误的,但是一运行就会报错:

ERROR org.apache.pig.tools.grunt.Grunt - ERROR 1107: Cannot merge join keys, incompatible types

这是因为a、b具有不同的类型:int和chararray。


转载于:https://my.oschina.net/u/1170537/blog/384426

 类似资料: