我正在使用Pig 0.8.1。我对Pig有点新,但我知道必须有一个合理且可重复使用的解决方案,以便我如何使用我的元组。我有以下格式(类似于三元组):
Schema: (uuid, key, val)
Data:
(id1, 'name', 'Corey')
(id1, 'location', 'USA')
(id1, 'carsOwned', 5)
(id2, 'name', 'Paul')
(id2, 'location', 'CANADA')
(id2, 'carsOwned', 10)
我在三元组中表示这些数据的原因是因为它可能具有多值键,因此将数据推送到地图是不可能的。
我需要做的是找到拥有前10辆车的人的ID,名称和位置。如果我的输出格式按降序排序,我会喜欢它:
Schema: (uuid, name, location, carsOwned)
Data:
(id2, 'Paul', 'CANADA', 10)
(id1, 'Corey', 'USA', 5)
我尝试将输入过滤为3个不同的别名(其中一个是key =='name',一个是key =='location',另一个是key =='carsOwned')所以我可以使用JOIN并带来它们回到一个元组,但看起来Pig最终从inputFormat加载3次而不是一次。也许我做错了?
我也尝试按ID进行分组,但是我似乎找不到合理的方法来处理实际三键/值的包,因为它们都具有完全相同的模式。
我真正想要的是按id字段分组,然后展平每个键,但将别名重命名为键的实际名称。
有什么想法吗?提前谢谢!
答案 0 :(得分:2)
这个解决方案有点草率,因为你的数据没有以Pig真正设置的方式组织 - 也就是说,概念上每个id都显示为一个行键,其中的字段以你在第二个中所拥有的字段命名柱。但只要您的数据合理,这仍然可以完成。如果您错误地使用具有相同ID和字段名称但具有不同值的多行,这将变得复杂。
使用嵌套的foreach选择您感兴趣的三个字段的值。
keyedByID =
/* Gather the rows by ID, then process each one in turn */
FOREACH (GROUP Data BY id) {
/* Pull out the fields you want. If you have duplicate rows,
you'll need to use a LIMIT statement to ensure just a single record */
name = FILTER Data BY field == 'name';
location = FILTER Data BY field == 'location';
carsOwned = FILTER Data BY field == 'carsOwned';
GENERATE
/* Output each field you want. You'll need to use FLATTEN since
the things created above in the nested foreach are bags. */
group AS id,
FLATTEN(name) AS name,
FLATTEN(locatioN) AS location,
FLATTEN(carsOwned) AS carsOwned;
};
现在你已经建立了一个将ID的所有信息放在一行上的关系,你可以随心所欲地使用它。例如,你说想要拔出前10名车主:
ordered = ORDER keyedByID BY carsOwned DESC;
top10 = LIMIT ordered 10;