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

时间:2010-11-01 14:07:43

标签: syntax map hadoop apache-pig

我想使用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的地图类型是半生不熟的吗?我错过了什么?

6 个答案:

答案 0 :(得分:2)

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

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

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

答案 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数据将包含相应的地图。

如何处理地图数据?

实际上有两个用例:

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

  2. 地图键是变量。 在这些情况下,您很可能希望使用其他一些数据集加入Map键。我通常使用UDF MapToBag 将Map转换为Bag,它将地图数据转换为Bag of 2 field元组(key,value)。一旦地图数据转换为Bag of tuples,就很容易将其与其他数据集连接起来。

  3. 我希望这会有所帮助。

答案 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)}"

我的文件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)} | [编程#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('#')

,然后读取为映射数据。