使用 Pig 加载 Json 数据
Posted
技术标签:
【中文标题】使用 Pig 加载 Json 数据【英文标题】:Load Json Data using Pig 【发布时间】:2015-02-06 13:41:46 【问题描述】:我正在尝试使用 jsonLoader()
从猪下面提到的 json 格式中提取数据:
"Partition":"10","Key":"618897","Properties2":["K":"A","T":"String","V":"M ", "K":"B","T":"String","V":"N", "K":"D","T":"String","V":"O"]
"Partition":"11","Key":"618900","Properties2":["K":"A","T":"String","V":"W”","K":"B","T":"String","V":"X", "K":"C","T":"String","V":"Y","K":"D","T":"String","V":"Z"]
现在我可以使用以下代码从每个数组对象的“partition”、“key”和“V”中提取数据:
A= LOAD '/home/hduser/abc.jon' Using JsonLoader('Partition:chararray,Key:chararray,Properties2:(K:chararray,T:chararray,V:chararray),Timestamp:chararray');
B= foreach A generate $0,$1,BagToString(Properties2.V,'\t') as vl:chararray;
store B into './Result/outPut2';
从上面的代码中,我得到的是基于序列而不是基于列的“Properties2”数组值,只要序列改变或新对象存在,就会产生问题。 请帮我根据列(K值)提取数据。
我的输出
预期输出
提前致谢
【问题讨论】:
【参考方案1】:这里有两种选择
1.使用elephant-bird,它将为您提供键和值的映射。
A = LOAD '/apps/pig/json_sample' USING com.twitter.elephantbird.pig.load.JsonLoader('-nestedLoad') as (json:map[]);
B = FOREACH A GENERATE json#'Partition',json#'Key',json#'Properties2';
dump B;
会给你一个输出:
(10,618897,([T#String,K#A,V#M ]),([T#String,K#B,V#N]),([T#String,K#D,V#O]))
(11,618900,([T#String,K#A,V#W”]),([T#String,K#B,V#X]),([T#String,K#C,V#Y]),([T#String,K#D,V#Z]))
或者您必须编写一个必须执行此操作的自定义加载器
a).它应该知道即将到来的正确的值顺序是什么 对于键 K
b)。遍历这些值中的每一个,查看 json 是否缺少此键中的任何一个,并为该位置返回一个空/null 字符。
我正在发布 CustomJsonLoader 的 getNext() 方法,它会做同样的事情:
@Override
public Tuple getNext() throws IOException
// TODO Auto-generated method stub
try
boolean notDone = in.nextKeyValue();
if (!notDone)
return null;
Text value = (Text) in.getCurrentValue();
List<String> valueList = new ArrayList<String>();
if (value != null)
String jsonString = value.toString();
System.out.println(jsonString);
JSONParser parser = new JSONParser();
JSONObject obj = null;
try
obj = (JSONObject) parser.parse(jsonString);
catch (ParseException e)
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("obj is "+obj);
if (obj != null)
String partition = (String) obj.get("Partition");
String key = (String) obj.get("Key");
valueList.add(partition);
valueList.add(key);
JSONArray innArr = (JSONArray) obj.get("Properties2");
char[] innKeys = new char[] 'A', 'B', 'C', 'D' ;
Map<String,String> keyMap = new HashMap<String,String>();
for (Object innObj : innArr)
JSONObject jsonObj = (JSONObject) innObj;
keyMap.put(jsonObj.get("K")+"",jsonObj.get("V")+"");
for (int i = 0; i < innKeys.length; i++)
char ch = innKeys[i];
if (keyMap.containsKey(ch+""))
valueList.add(keyMap.get(ch+""));
else
valueList.add("");
Tuple t = tupleFactory.newTuple(valueList);
return t;
return null;
catch (InterruptedException e)
并注册并运行:
REGISTER udf/CustomJsonLoader.jar
A = LOAD '/apps/pig/json_sample' USING CustomJsonLoader();
DUMP A;
(10,618897,M,N,,O)
(11,618900,W,X,Y,Z)
希望这会有所帮助!
【讨论】:
非常感谢您的时间和精力,我尝试使用大象鸟得到相同的结果,但无法根据列(基于 K 值)获取值。我是 pig 的新手,udf 部分对我来说有点困难,请你帮我解决 customjsonLoader 的先决条件,比如 jar 和代码。 arunxjacob.blogspot.in/2010/12/writing-custom-pig-loader.html 这是一个非常简单的博客,我最初遵循它来创建自定义加载器。如果你懂 java,为 pig 编写 udf/loader/store 函数很容易。 感谢您的回复,我浏览了您建议的博客,并在您的帮助下准备了自定义加载程序,但它无法正常工作当我通过以下错误执行我的猪脚本时:错误 1070 :无法使用导入解析客户:[, java.lang., org.apache.pig.builtin., org.apache.pig.impl.builtin.] at org.apache.pig.parser.QueryParserDriver.parse(QueryParserDriver. java:196) 在 org.apache.pig.PigServer$Graph.parseQuery(PigServer.java:1676) 在 org.apache.pig.PigServer$Graph.access$000(PigServer.java:1409) .....跨度> 您的 udf 注册似乎失败了。确保类文件正在扩展 LoadFunc,并且 jar 文件在您在注册时提到的路径中可用。 能否分享一下注册的命令,你的包名和类名,以及使用udf的命令以上是关于使用 Pig 加载 Json 数据的主要内容,如果未能解决你的问题,请参考以下文章
从 ES 加载数据并使用 pig 在 HDFS 中存储为 avro
将 Hadoop Pig 输出作为 JSON 数据发布到 URL?