1

使用 Apache Pig 版本 0.10.1.21(重新导出)

数据样本文件内容:

AtomicNumber,ElementName,Symbol,AtomicMass,PropertyMap
46,Palladium,Pd,106.42,[P#46,N#60,Struc#Cubic]
49,Indium,In,114.818,[P#49,N#66,Struc#Tetragonal]
52,Tellurium,Te,127.6,[P#52,N#76,Struc#Hexagonal]
86,Radon,222.0,Rn,[P#86,N#136,Struc#Cubic]
38,Strontium,Sr,87.62,[P#38,N#50,Struc#Cubic]
Plutonium,94,Pu,244.0,[P#94,N#150,Struc#Monoclinic]

注意:有意交换某些列(对于 Radon 和 Plutonium),以查看 Pig 如何处理数据类型不匹配

猪脚本:

AtomElem = LOAD 'data/Atoms.txt' USING PigStorage(',') AS (AtomicNumber:int, ElementName:chararray, Symbol:chararray, AtomicMass:float, PropertyMap:map[]);
DUMP AtomElem;

结果:

(,ElementName,Symbol,,)
(46,Palladium,Pd,106.42,)
(49,Indium,In,114.818,)
(52,Tellurium,Te,127.6,)
(86,Radon,222.0,,)
(38,Strontium,Sr,87.62,)
(,94,Pu,244.0,)

问题1:我希望显示 PropertyMap。您能否告诉我如何修改 pig 脚本或数据文件,以便将 PropertyMap 列显示为地图数据类型。

问题2:在地图模式的声明中,我想强类型数据类型。我将架构声明为 PropertyMap:map[int, int, chararray] 但 pig 拒绝了语法(错误,预计右括号)。是否可以声明具有多个键的地图?如果是,架构声明应该是什么样的?

提前感谢您的帮助。

4

2 回答 2

1

您的脚本未成功生成地图的原因是您使用逗号作为字段分隔符,但它也是地图键值对的分隔符。因此,当 Pig 将您的行拆分为字段时,第五个字段不是[P#46,N#60,Struc#Cubic]您所期望的,而是[P#46. Pig 无法成功将其解析为地图,因此将其转换为NULL.

至于您的第二个问题,您不能指定各个地图值的数据类型。首先,秩序在地图中没有任何意义。一张地图可以有任意数量的元素。如果你想为你的所有值指定一个单一的数据类型,你可以这样做,但除此之外,Pig 会找出它是什么类型,或者你需要在使用它时显式地转换该值。

为了说明这两点,我已将您的输入数据修改为制表符分隔(并相应地将脚本更新为USING PigStorage('\t')),并交换了第二行中两个地图元素的位置,以表明 Pig 不会重现它们的顺序中提供。

$ cat data.txt
AtomicNumber    ElementName     Symbol  AtomicMass      PropertyMap
46      Palladium       Pd      106.42  [P#46,N#60,Struc#Cubic]
49      Indium  In      114.818 [N#66,Struc#Tetragonal,P#49]
52      Tellurium       Te      127.6   [P#52,N#76,Struc#Hexagonal]
86      Radon   222.0   Rn      [P#86,N#136,Struc#Cubic]
38      Strontium       Sr      87.62   [P#38,N#50,Struc#Cubic]
Plutonium       94      Pu      244.0   [P#94,N#150,Struc#Monoclinic]

$ cat test.pig
AtomElem = LOAD 'data.txt' USING PigStorage('\t') AS (AtomicNumber:int, ElementName:chararray, Symbol:chararray, AtomicMass:float, PropertyMap:map[]);
DUMP AtomElem;

$ pig -x local test.pig
(,ElementName,Symbol,,)
(46,Palladium,Pd,106.42,[P#46,N#60,Struc#Cubic])
(49,Indium,In,114.818,[P#49,N#66,Struc#Tetragonal])
(52,Tellurium,Te,127.6,[P#52,N#76,Struc#Hexagonal])
(86,Radon,222.0,,[P#86,N#136,Struc#Cubic])
(38,Strontium,Sr,87.62,[P#38,N#50,Struc#Cubic])
(,94,Pu,244.0,[P#94,N#150,Struc#Monoclinic])
于 2013-05-09T21:24:16.917 回答
0

就个人而言,我会将所有数据存储为 JSON 并从中加载。当您加载的数据集中有复杂的数据结构时,它会让您和之后从事此工作的任何人更容易管理事情,因为 JSON 是比加载地图等更直接的嵌套结构标准......猪。

我认为@WinnieNicklaus 的答案也应该有效,但是下一个从事此工作的人,或者下次您需要向数据中添加一些复杂的东西时,您会遇到同样的问题。只需将所有内容存储在 JSON 中并使用Pig 的内置 JSON 加载器加载

a = load 'a.json' using 
JsonLoader('a0:int,a1:{(a10:int,a11:chararray)},a2:(a20:double,a21:bytearray),a3:[chararray]');

如果您不想提供模式,也可以使用 ElephantBird 的 JSON 加载器进行加载:

loaded = LOAD '/path/to/some_file.json'
    using com.twitter.elephantbird.pig.load.JsonLoader('-nestedLoad');

如果我没记错的话,这两个文件都应该适用于 .gz 文件,并且大象鸟版本也适用于 lzos。

于 2013-05-09T21:34:28.170 回答