使用Apache Pig版本0.10.1.21(rexported)
数据样本文件的内容:
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列显示为map数据类型。
Question2 :在地图模式的声明中,我想强类型化数据类型。我将模式声明为PropertyMap:map [int,int,chararray]但是pig拒绝了语法(错误,右括号预期)。是否可以声明具有多个键的地图?如果是,那么架构声明应该是什么样的?
提前感谢您的帮助。
答案 0 :(得分: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])
答案 1 :(得分:0)
就个人而言,我将所有数据存储为JSON并从中加载。当您在加载的数据集中有复杂的数据结构时,它将使您和之后处理此事的任何人更容易管理,因为JSON是嵌套结构比直接加载地图等更直接的标准...猪。
我认为@WinnieNicklaus的答案也应该有效,但是下一个人正在处理这个问题,或者下次你需要为数据添加一些复杂的东西时,你会遇到同样的问题。只需将所有内容存储在JSON中,然后使用Pig's Built-in JSON loader加载:
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文件,而且elephantbird版本也适用于lzos。