Apache Pig — вызов Java UDF ToJSON несколько раз в скрипте

(Первый пост!)

Я играл с примером набора данных резюме. Объект резюме несколько сложен, с несколькими подобъектами. На текущем этапе моего плана я пытаюсь сгладить набор данных, сохраняя подобъекты в виде строк JSON. Я столкнулся с проблемой схемы с UDF ToJSON. (https://github.com/rjurney/pig-to-json)

Если я сделаю следующий оператор в своем скрипте Pig, я получу правильные данные в своих полях, но он повторно использует имена полей Positions для всех вызовов ToJSson():

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\"}]"
}

person Steve Cardella    schedule 13.10.2015    source источник


Ответы (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});

Затем в самом скрипте свиньи я добавил несколько предложений 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
  ;
person Steve Cardella    schedule 15.10.2015