Pig加载同元素不同Schema的JSON文件时的过滤异常问题求助
解决Pig加载JSON时字段类型不一致导致的过滤报错问题
这个问题我之前处理异构JSON数据时碰到过,核心原因就是你JSON里的program字段同时存在字符串和数组两种格式,用Elephant Bird的JsonLoader加载后,字符串会被解析成chararray,数组则会变成bag类型。你强行把所有值转成chararray时,Bag类型的字段根本转不动,后面用MATCHES过滤Bag自然会报错。
解决思路
得先给每条记录的program字段做类型判断,再针对不同类型做适配处理:
- 要是字段是字符串类型,直接用原字段做匹配就行;
- 要是字段是Bag类型,得先把Bag扁平化(或者按需取里面的元素),再做匹配判断。
具体代码实现
-- 加载原始JSON数据 rel = LOAD '$filePath' USING com.twitter.elephantbird.pig.load.JsonLoader('-nestedLoad') AS (json:map []); -- 先获取program字段的类型,同时保留原始字段 with_type = FOREACH rel GENERATE json#'program' AS program, TYPE(json#'program') AS program_type; -- 分类型处理:字符串直接保留,Bag则扁平化 processed = FOREACH with_type GENERATE (program_type == 'chararray' ? program : FLATTEN(program)) AS processed_program, program_type; -- 执行过滤:匹配字符串类型的'open',或者Bag中包含'open'的记录 open = FILTER processed BY (program_type == 'chararray' AND processed_program MATCHES 'open') OR (program_type == 'bag' AND processed_program MATCHES 'open'); -- 要是需要保留原始的完整记录,可以把处理后的结果和原始表关联回去(可选) final_result = JOIN rel BY json#'program', open BY processed_program;
额外说明
- 如果你的需求是只要
program的值是"open"(不管是字符串本身,还是数组里包含这个值),上面的逻辑都能覆盖; - 要是数组场景下你只需要判断第一个元素,不用
FLATTEN,直接用program.$0取Bag里的第一个元素就行; - 别想着加载时用固定Schema强转,因为字段类型本身不固定,动态判断类型才是最稳妥的方案。
内容的提问来源于stack exchange,提问作者ANTHOLB
相关产品推荐
相关产品推荐

