1

请考虑以下 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)

任何解决此问题的帮助将不胜感激!

4

1 回答 1

0

尝试使用 FLATTEN 将地图从包中取出。

于 2015-08-05T20:21:15.167 回答