我想使用Apache Pig来构建一个大密钥 - >值映射,在地图中查找内容,并迭代键。然而,甚至似乎没有做这些事情的语法;我检查了手册,维基,示例代码,象书,谷歌,甚至尝试解析解析器源。每个示例都从文件加载地图文字...然后从不使用它们。你怎么用Pig的地图?
首先,似乎没有办法直接将2列CSV文件加载到地图中。如果我有一个简单的map.csv
:
1,2
3,4
5,6
我尝试将其加载为地图:
m = load 'map.csv' using PigStorage(',') as (M: []);
dump m;
我得到三个空元组:
()
()
()
所以我尝试加载元组然后生成地图:
m = load 'map.csv' using PigStorage(',') as (key:chararray, val:chararray);
b = foreach m generate [key#val];
ERROR 1000: Error during parsing. Encountered " "[" "[ "" at line 1, column 24.
...
语法的许多变体也会失败(例如generate [$0#$1]
)。
好的,所以我把我的地图变成猪的地图文字格式为map.pig
:
[1#2]
[3#4]
[5#6]
加载它:
m = load 'map.pig' as (M: []);
现在让我们加载一些键并尝试查找:
k = load 'keys.csv' as (key);
dump k;
3
5
1
c = foreach k generate m#key; /* Or m[key], or... what? */
ERROR 1000: Error during parsing. Invalid alias: m in {M: map[ ]}
嗯,好吧,也许因为涉及两个关系,我们需要一个联接:
c = join k by key, m by /* ...um, what? */ $0;
dump c;
ERROR 1068: Using Map as key not supported.
c = join k by key, m by m#key;
dump c;
Error 1000: Error during parsing. Invalid alias: m in {M: map[ ]}
失败。如何引用地图的键(或值)?地图模式语法似乎不允许您为键和值命名(邮件列表表示无法分配类型)。
最后,我希望能够在我的地图中找到所有键:
d = foreach m generate ...oh, forget it.
Pig的地图类型是半生不熟的吗?我错过了什么?
答案 0 :(得分:2)
目前,猪地图需要您提供的chararray(字符串)的键,而不是包含字符串的变量。所以在map#key中,键必须是你提供的常量字符串(例如:map#'keyvalue')。
这种情况的典型用例是加载一个复杂的数据结构,其中一个元素是一个键值对,然后在foreach语句中,您可以根据您感兴趣的键引用一个特定的值。
答案 1 :(得分:1)
在Pig版本0.10.0中,有一个名为“TOMAP”(http://pig.apache.org/docs/r0.10.0/func.html#tomap)的新功能可将其奇数(chararray)参数转换为键,甚至将参数转换为值。不幸的是,我没有发现它有用,因为我通常处理不同长度和键的任意词。
我会找到一个TOMAP函数,它将一个元组作为单个参数而不是可变数量的参数,更有用。
这不是解决您问题的完整解决方案,但TOMAP的可用性为您构建真正的解决方案提供了更多选择。
答案 2 :(得分:1)
好问题! 我个人不喜欢Pig in Pig。它们在Java,C#等传统编程语言中占有一席之地,其中在地图中查找键非常方便快捷。另一方面,Pig in Maps的功能非常有限。
正如你正确指出的那样,人们无法在Pig in Map中查找变量键。关键需要是常量。例如myMap#'keyFoo'是允许的,但不允许myMap#$ SOME_VARIABLE。
如果你考虑一下,你就不需要Pig in Pig。通常从一些源加载数据,对其进行转换,将其与其他数据集连接,对其进行过滤,转换等等。 JOIN实际上可以很好地查找数据中的变量键。 例如data1有2列A和B,data2有3列X,Y,Z。如果你将data1 BY A与data2 BY Z连接起来,JOIN会完成Map(来自传统语言)的工作,它将列Z的值映射到值B栏(通过A栏)。因此,data1基本上代表地图A - >乙
那么为什么我们需要Pig中的Map?
通常,Hadoop数据是来自传统语言的不同数据源的转储。如果原始数据源包含地图,则HDFS数据将包含相应的地图。
如何处理地图数据?
实际上有两个用例:
地图键是常量。 例如HttpRequest标头数据包含时间,服务器,clientIp作为Map中的键。要访问特定键的值,一种情况下使用Constant键访问它们。 例如标题# 'clientIp'。
地图键是变量。 在这些情况下,您很可能希望使用其他一些数据集加入Map键。我通常使用UDF MapToBag 将Map转换为Bag,它将地图数据转换为Bag of 2 field元组(key,value)。一旦地图数据转换为Bag of tuples,就很容易将其与其他数据集连接起来。
我希望这会有所帮助。
答案 3 :(得分:1)
1)如果你想加载地图数据,它应该像#34; [编程#SQL,rdbms#Oracle]"
2)如果你想加载元组数据,它应该像"(first_name_1234,middle_initial_1234,last_name_1234)"
3)如果你想加载行李数据,它应该像" {(project_4567_1),(project_4567_2),(project_4567_3)}"
1234 | emp_1234@company.com |(first_name_1234,middle_initial_1234,last_name_1234)| {(project_1234_1),(project_1234_2),(project_1234_3)} | [编程#SQL,RDBMS#甲骨文] 4567 | emp_4567@company.com |(first_name_4567,middle_initial_4567,last_name_4567)| {(project_4567_1),(project_4567_2),(project_4567_3)} | [编程#Java中,OS#的Linux]
我的架构:
a = LOAD' pigtest.csv'使用PigStorage(' |')AS(employee_id:int,email:chararray,name:tuple(first_name:chararray,middle_name:chararray,last_name:chararray),project_list:bag {project:tuple(project_name: chararray)},技能:地图[chararray]);
b = FOREACH a GENERATE employee_id,email,name.first_name,project_list,skills#' programming' ;
转储b;
答案 4 :(得分:0)
我认为你需要用relations来思考,map只是一个记录中的一个字段。然后,您可以对关系应用一些operations,例如加入两组数据和映射:
输入
$ cat data.txt
1
2
3
4
5
$ cat mapping.txt
1 2
2 4
3 6
4 8
5 10
猪
mapping = LOAD 'mapping.txt' AS (key:CHARARRAY, value:CHARARRAY);
data = LOAD 'data.txt' AS (value:CHARARRAY);
-- list keys
mapping_keys =
FOREACH mapping
GENERATE key;
DUMP mapping_keys;
-- join mapping to data
mapped_data =
JOIN mapping BY key, data BY value;
DUMP mapped_data;
输出
> # keys
(1)
(2)
(3)
(4)
(5)
> # mapped data
(1,2,1)
(2,4,2)
(3,6,3)
(4,8,4)
(5,10,5)
如果你只想做一个简单的查找,这个答案也可以帮到你: pass-a-relation-to-a-pig-udf-when-using-foreach-on-another-relation
答案 5 :(得分:0)
您可以加载任何数据,然后以键值格式进行转换和存储以供以后使用
data = load 'somedata.csv' using PigStorage(',')
STORE data into 'folder' using PigStorage('#')
,然后读取为映射数据。