21

我想使用 Apache Pig 构建一个大键 -> 值映射,在映射中查找内容,然后遍历键。然而,做这些事情似乎没有语法;我检查了手册、wiki、示例代码、大象书、谷歌,甚至尝试解析解析器源。每个示例都从文件中加载地图文字......然后从不使用它们。如何使用 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])。

好的,所以我将我的地图转换为 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[ ]}

Hrm,好吧,可能因为涉及到两个关系,我们需要一个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[ ]}

失败。如何引用地图的键(或值)?映射模式语法似乎不允许您命名键和值(邮件列表说无法分配类型)。

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

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

猪的地图类型是半生不熟的吗?我错过了什么?

4

6 回答 6

2

目前,猪地图需要您提供的 chararray(字符串)的键,而不是包含字符串的变量。因此在 map#key 中,键必须是您提供的常量字符串(例如:map#'keyvalue')。

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

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

于 2011-11-23T07:30:45.573 回答
1

在 Pig 版本 0.10.0 中,有一个名为“TOMAP”(http://pig.apache.org/docs/r0.10.0/func.html#tomap)的新函数可以将其奇数(chararray)参数转换为键和甚至参数值。不幸的是,我发现它并没有那么有用,因为我通常处理不同长度和键的任意字典。

我会发现将元组作为单个参数而不是可变数量的参数的 TOMAP 函数更有用。

这不是您问题的完整解决方案,但 TOMAP 的可用性为您提供了更多选择来构建真正的解决方案。

于 2012-07-30T19:07:24.910 回答
1

好问题!我个人不喜欢 Pig 中的 Maps。它们在 Java、C# 等传统编程语言中占有一席之地,其中在地图中查找键非常方便快捷。另一方面,Pig 中的地图功能非常有限。

正如您正确指出的那样,无法在 Pig 的 Map 中查找变量键。密钥必须是常量。例如 myMap#'keyFoo' 是允许的,但 myMap#$SOME_VARIABLE 是不允许的。

如果您考虑一下,您不需要在 Pig 中使用 Map。人们通常从某个来源加载数据,对其进行转换,将其与其他数据集连接,对其进行过滤,对其进行转换等等。JOIN 实际上在查找数据中的变量键方面做得很好。例如,data1 有 2 列 A 和 B,而 data2 有 3 列 X、Y、Z。如果将 data1 BY A 与 data2 BY Z 连接起来,则 JOIN 会执行 Map(来自传统语言)的工作,将 Z 列的值映射到值B 列(通过 A 列)。所以 data1 本质上代表了一个 Map A -> B。

那么为什么我们需要在 Pig 中使用 Map 呢?

通常 Hadoop 数据是来自传统语言的不同数据源的转储。如果原始数据源包含 Maps,则 HDFS 数据将包含相应的 Map。

如何处理地图数据?

实际上有2个用例:

  1. 映射键是常量。例如,HttpRequest Header 数据包含时间、服务器、clientIp 作为 Map 中的键。要访问特定键的值,一种情况是使用常量键访问它们。例如标头#'clientIp'。

  2. 映射键是变量。在这些情况下,您很可能希望将 Map 键与其他一些数据集连接起来。我通常使用 UDF MapToBag将 Map 转换为 Bag ,它将地图数据转换为包含 2 个字段元组(键、值)的 Bag。将地图数据转换为元组包后,很容易将其与其他数据集连接起来。

我希望这有帮助。

于 2015-10-20T07:27:57.677 回答
1

1)如果你想加载地图数据,它应该像“[programming#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 = LOAD 'pigtest.csv' using PigStorage('|') AS (employee_id:int, email:chararray, name:tuple(first_name:chararray, middle_name:chararray, last_name:chararray), project_list:bag{project: tuple(项目名称:字符数组)},技能:地图[字符数组]);

b = FOREACH a GENERATE employee_id, email, name.first_name, project_list, Skills#'programming' ;

转储 b;

于 2017-05-29T06:35:13.440 回答
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)

如果您只想做一个简单的查找,这个答案也可以帮助您: pass-a-relation-to-a-pig-udf-when-using-foreach-on-another-relation

于 2010-12-07T18:45:02.927 回答
0

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

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

然后读取为映射数据。

于 2018-08-06T19:33:09.230 回答