(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。