Apache Pig - 在脚本中多次调用 Java UDF ToJSON

Posted

技术标签:

【中文标题】Apache Pig - 在脚本中多次调用 Java UDF ToJSON【英文标题】:Apache Pig - calling Java UDF ToJSON multiple times in a script 【发布时间】:2015-10-13 21:51:43 【问题描述】:

(第一次发帖!)

我一直在玩一个示例简历数据集。 resume 对象有点复杂,有多个子对象。对于我计划的当前阶段,我试图通过将子对象存储为 JSON 字符串来展平数据集。我遇到了 ToJSON UDF 的架构问题。 (https://github.com/rjurney/pig-to-json)

如果我在我的 Pig 脚本中执行以下语句,我会在我的字段中获得正确的 data,但它会为所有 ToJSson() 调用重用 Positions 字段名称:

stringifiedJSON =
FOREACH fullJSON
GENERATE
id ..  TotalYears,
com.hortonworks.pig.udf.ToJson(Awards) AS Awards:chararray,
com.hortonworks.pig.udf.ToJson(Certifications) AS Certifications:chararray,
CASE WHEN Degrees IS NULL THEN ‘[]’ ELSE com.hortonworks.pig.udf.ToJson(Degrees) END AS Degrees:chararray,
com.hortonworks.pig.udf.ToJson(Links) AS Links:chararray,
com.hortonworks.pig.udf.ToJson(Groups) AS Groups:chararray,
com.hortonworks.pig.udf.ToJson(MilitaryService) AS MilitaryService:chararray,
com.hortonworks.pig.udf.ToJson(Positions) AS Positions:chararray;

如果我描述“fullJSON”数据集,这就是我得到的回报(“...”是与讨论无关的其他字段):

fullJSON:

id: chararray,
..
Awards: award: (AwardDate: chararray,AwardDescription: chararray,AwardTitle: chararray),
Certifications: certification: (CertDescription: chararray,CertEndDate: chararray,CertStartDate: chararray,CertTitle: chararray),
…
Degrees: (DegreeTitle: chararray,DegreeEndDate: chararray,DegreeStartDate: chararray,School: chararray,SchoolCity: chararray,SchoolState: chararray,DegreeEducationLevel: chararray),
…
Links: link: (LinkTitle: chararray,LinkURL: chararray),
Groups: group: (GroupDescription: chararray,GroupEndDate: chararray,GroupStartDate: chararray,GroupTitle: chararray),
…
MilitaryService: military_service: (MilitaryBranch: chararray,MilitaryCommendations: chararray,MilitaryCountry: chararray,MilitaryDescripton: chararray,MilitaryStartDate: chararray,MilitaryEndDate: chararray,MilitaryRank: chararray),
…
Positions: (Company: chararray,CompanyCity: chararray,CompanyState: chararray,JobStartDate: chararray,JobEndDate: chararray,JobTitle: chararray,IsCurrentTitle: int),
…

有人有什么想法吗?我尝试将 ToJson() 调用拆分为各自的步骤,但得到了相同的结果。

我后来稍微玩了一下 ToJSON.java 的源代码,我想我已经将其范围缩小到以下代码。我在此之后立即添加了 strSchema 的日志输出,它总是返回相同的信息(位置信息)。

if (myProperties == null) 
    // Retrieve our class specific properties from UDFContext
    myProperties = UDFContext.getUDFContext().getUDFProperties(this.getClass());
    

String strSchema = myProperties.getProperty("horton.json.udf.schema");

这是 stringifiedJSON 输出的示例:


  "id":"http://something.com/some_guy",
  ...
  "Awards":"[]",
  "Certifications":"[]",
  "Degrees":"[\"CompanyState\":null,\"CompanyCity\":null,\"JobEndDate\":\"\",\"IsCurrentTitle\":\"Bachelor's Degree\",\"JobTitle\":\"\",\"Company\":\"BS in Marketing\",\"JobStartDate\":\"State University\"]",
  "Links":"[]",
  "Groups":"[]",
  "MilitaryService":"[]",
  "Positions":"[\"CompanyState\":\"AZ\",\"CompanyCity\":\"Scottsdale\",\"JobEndDate\":\"2010-03-01T00:00:00.000Z\",\"IsCurrentTitle\":0,\"JobTitle\":\"Job runner\",\"Company\":\"somecompany\",\"JobStartDate\":\"2005-06-01T00:00:00.000Z\",\"CompanyState\":\"AZ\",\"CompanyCity\":\"Scottsdale\",\"JobEndDate\":\"2010-03-01T00:00:00.000Z\",\"IsCurrentTitle\":0,\"JobTitle\":\"Sales Rep\",\"Company\":\"Company2\",\"JobStartDate\":\"2005-06-01T00:00:00.000Z\",\"CompanyState\":\"AZ\",\"CompanyCity\":\"Phoenix\",\"JobEndDate\":\"2004-12-01T00:00:00.000Z\",\"IsCurrentTitle\":0,\"JobTitle\":\"Job 3\",\"Company\":\"Company3\",\"JobStartDate\":\"1991-05-01T00:00:00.000Z\",\"CompanyState\":\"AZ\",\"CompanyCity\":\"Phoenix\",\"JobEndDate\":\"2004-12-01T00:00:00.000Z\",\"IsCurrentTitle\":0,\"JobTitle\":\"CompanyRep\",\"Company\":\"Company4\",\"JobStartDate\":\"1991-05-01T00:00:00.000Z\",\"CompanyState\":\"AZ\",\"CompanyCity\":\"Phoenix\",\"JobEndDate\":null,\"IsCurrentTitle\":null,\"JobTitle\":\"Job5\",\"Company\":\"Company5\",\"JobStartDate\":\"2014-09-01T00:00:00.000Z\"]"

【问题讨论】:

【参考方案1】:

这就是我最终要做的事情。我会很多用不同的方式来完成它,但它确实有效。我宁愿不必在开始时进行 7 次不同的 DEFINE 调用,而是能够调用函数本身并让它正常工作。

我在类中添加了一个名为签名的字符串和一个构造函数:

String signature = null;
public ToJson(String Signature) 
    signature = Signature;

我修改了类的 outputSchema()。我将签名添加到 getUDFProperties:

Properties udfProp = context.getUDFProperties(this.getClass(),new String[]signature);

我同样修改了 exec():

myProperties = UDFContext.getUDFContext().getUDFProperties(this.getClass(),new String[]signature);

然后,在 pig 脚本本身中,我添加了几个 DEFINE 子句:

DEFINE awardToJson com.hortonworks.pig.udf.ToJson('award');
DEFINE certToJson com.hortonworks.pig.udf.ToJson('cert');
DEFINE degreeToJson com.hortonworks.pig.udf.ToJson('degree');
DEFINE linkToJson com.hortonworks.pig.udf.ToJson('link');
DEFINE groupToJson com.hortonworks.pig.udf.ToJson('group');
DEFINE militaryToJson com.hortonworks.pig.udf.ToJson('military');
DEFINE positionToJson com.hortonworks.pig.udf.ToJson('position');

然后我调整了猪脚本中的函数调用:

stringifiedJSON =
  FOREACH fullJSON
  GENERATE
  id .. TotalYears,
  awardToJson(Awards) AS Awards:chararray,
  certToJson(Certifications) AS Certifications:chararray,
  CASE WHEN Degrees IS NULL THEN '[]' ELSE degreeToJson(Degrees) END AS Degrees:chararray,
  linkToJson(Links) AS Links:chararray,
  groupToJson(Groups) AS Groups:chararray,
  militaryToJson(MilitaryService) AS MilitaryService:chararray,
  positionToJson(Positions) AS Positions:chararray
  ;

【讨论】:

以上是关于Apache Pig - 在脚本中多次调用 Java UDF ToJSON的主要内容,如果未能解决你的问题,请参考以下文章

Apache Pig 中的按位运算?

执行远程 Apache Pig 脚本时如何查看终端日志

Apache PIG:pigstorage 不添加扩展

在 python 脚本中,如何忽略 Apache Pig 的 Python 装饰器以进行独立单元测试

运行 Apache Pig 脚本时如何查找 jar 依赖项?

PIG 脚本错误:java.lang.NoSuchMethodError:org.apache.thrift.protocol.TProtocol.getScheme