请考虑以下 PIG 数据:
search_values = FOREACH raw_search GENERATE
search_id,
user_id,
param_name,
param_value;
describe search_values;
search_values: {search_id: int,user_id: int,param_name: chararray,param_value: chararray}
dump search_values;
(1, 1, location, San Francisco)
(1, 1, type, Commercial)
每个 search_id/user_id 组合可能有多个记录;因此,我稍后在代码中对记录进行分组。但是,我只对两个特定的 param_name 感兴趣 - 'location' 和 'type':过滤 = FILTER search_values by (param_name == 'type' or param_name == 'location');
理论上,总是有一排有“位置”,还有一排有“类型”;但是,有些情况下“类型”不存在;因此,我需要将其替换为“全部”(稍后)。
我知道最简单的方法是按 param_name 拆分数据,然后按 search_id (OUTER) join;但是,我想在 PIG 中利用包的力量。
我尝试了各种使用包的方法,将包转换为地图无济于事:
maps = FOREACH filtered GENERATE search_id, user_id, TOMAP(param_name, param_value) as tomap_values;
group_map = group maps by (search_id, user_id);
grouped = FOREACH group_map GENERATE
group.$0 as search_id,
group.$1 as user_id,
maps.tomap_values as map_bag;
这里的问题是 map_bag 是包内的地图,我无法使用 map_bag#'type' 或 map_bag#'location' 从中提取值。
describe grouped:
{search_id: int,user_id: int,map_bag: {(tomap_values: map[])}}
如果我尝试以下操作,我会收到一条错误消息:
mapped = FOREACH grouped
GENERATE
search_id,
user_id,
map_bag.tomap_values#'type',
map_bag.tomap_values#'location';
ERROR 1052: Cannot cast bag with schema :bag{:tuple(tomap_values:map)} to map with schema :map
期望的结果应该是
(search_id, user_id, type, location)
(1, 1, Commercial, San Francisco)
任何解决此问题的帮助将不胜感激!