如何在Apache Pig中使用地图数据类型?

21
我想使用Apache Pig构建一个大型键值映射,查找映射中的内容,并遍历所有键。然而,似乎没有语法可用于完成这些操作。我已经查阅了手册、维基、示例代码、《大象书》、谷歌甚至尝试了解析解析器源代码,但每个例子都是从文件中加载映射文字……然后从未使用它们。你如何使用Pig的映射?
首先,似乎没有直接将2列CSV文件加载到Map中的方法。如果我有一个简单的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])。

好的,所以我将我的映射转换为Pig的映射字面格式,如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[ ]}

嗯,好的,也许由于涉及两个关系,我们需要使用联接(join):

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[ ]}

失败。如何引用map的键(或值)?映射模式语法似乎甚至不能让你命名键和值(邮件列表说没有办法分配类型)。

最后,我只想能够找到我的地图中所有的键:

d = foreach m generate ...oh, forget it.

Pig的map类型不完善吗?我错过了什么?

6个回答

2

目前,Pig Maps需要您提供一个chararray(字符串)类型的键值,而不是包含字符串的变量。因此,在map#key中,键必须是您提供的常量字符串(例如:map#'keyvalue')。

典型的用例是加载一个复杂的数据结构,其中一个元素是键值对,并且稍后在foreach语句中,您可以根据您感兴趣的键引用特定的值。

http://pig.apache.org/docs/r0.9.1/basic.html#map-schema


1
很好的问题!我个人不喜欢 Pig 中的 Maps。它们在传统编程语言(如 Java、C# 等)中有用武之地,因为在 Map 中查找键非常方便和快捷。另一方面,Pig 中的 Maps 功能非常有限。
正如你所指出的,无法在 Pig 的 Map 中查找变量键。键需要是常量。例如 myMap#'keyFoo' 是允许的,但 myMap#$SOME_VARIABLE 不允许。
如果你仔细想想,你其实不需要在 Pig 中使用 Map。通常,我们会从某些源加载数据,对其进行转换,与其他数据集合并,过滤,转换等操作。JOIN 实际上很好地完成了在数据中查找变量键的工作。
例如,data1 有两列 A 和 B,data2 有三列 X、Y、Z。如果你通过 A 将 data1 与 Z 将 data2 进行 JOIN,则 JOIN 执行了一个 Map(从传统语言的角度来看),将列 Z 的值映射到列 B 的值(通过列 A)。因此,data1 本质上表示一个 Map A->B。
那么,我们为什么需要 Pig 中的 Map 呢?
通常,Hadoop数据是来自传统语言的不同数据源的转储。如果原始数据源包含Map,则HDFS数据将包含相应的Map。
如何处理Map数据?
有两种用例:
1. Map键是常量。例如,HttpRequest标头数据包含时间、服务器、客户端IP作为Map中的键。要访问特定键的值,可以使用常量键访问它们。例如,header#'clientIp'。
2. Map键是变量。在这些情况下,您最有可能希望将Map键与某个其他数据集JOIN起来。我通常使用UDF MapToBag将Map转换为Bag,该函数将Map数据转换为2个字段元组(键,值)的Bag。一旦将Map数据转换为元组的Bag,就很容易将其与其他数据集JOIN起来。
希望这能帮到您。

1
在Pig版本0.10.0中,有一个名为"TOMAP"(http://pig.apache.org/docs/r0.10.0/func.html#tomap)的新函数可用,它将其奇数(chararray)参数转换为键,偶数参数转换为值。不幸的是,我发现它并不那么有用,因为我通常处理长度和键不同的任意字典。
我会发现一个以元组作为单个参数的TOMAP函数比可变数量的参数更有用。
这不是您问题的完整解决方案,但TOMAP的可用性为您构建真正解决方案提供了更多选项。

1

1)如果您想加载地图数据,应该像这样"[编程#SQL,rdbms#Oracle]"

2)如果您想加载元组数据,应该像这样"(first_name_1234,middle_initial_1234,last_name_1234)"

3)如果您想加载包数据,应该像这样"{(project_4567_1),(project_4567_2),(project_4567_3)}"

我的文件pigtest.csv长这样

1234|emp_1234@company.com|(first_name_1234,middle_initial_1234,last_name_1234)|{(project_1234_1),(project_1234_2),(project_1234_3)}|[programming#SQL,rdbms#Oracle] 4567|emp_4567@company.com|(first_name_4567,middle_initial_4567,last_name_4567)|{(project_4567_1),(project_4567_2),(project_4567_3)}|[programming#Java,OS#Linux]


我的架构:

a = 使用PigStorage('|')从'pigtest.csv'中LOAD数据,并将其命名为(employee_id:int, email:chararray, name:tuple(first_name:chararray, middle_name:chararray, last_name:chararray), project_list:bag{project: tuple(project_name:chararray)}, skills:map[chararray]) ;

b = 对a进行FOREACH操作,选择employee_id、email、name.first_name、project_list和skills#'programming'等字段;

dump b;


0

您可以加载任何数据,然后将其转换并存储为键值格式以供以后使用

data = load 'somedata.csv' using PigStorage(',')
STORE data into 'folder' using PigStorage('#')

然后将其作为映射数据进行读取。

0

我认为你需要从关系的角度 思考, 而映射只是一条记录中的一个字段。然后,你可以在这些关系上应用一些操作, 比如将两组数据映射进行连接:

输入

$ 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)

如果您只想进行简单的查找,此答案也可能对您有所帮助:在使用另一个关系的foreach时将关系传递给pig-udf


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接