복붙노트

[HADOOP] Hive에서 XML 데이터 행 분해

HADOOP

Hive에서 XML 데이터 행 분해

Hadoop에는 XML이라는 단일 문자열 열로 XML 데이터가로드됩니다. 우리는 데이터 레벨을 정규화하거나 처리하기 위해 단일 행으로 분해하려고합니다 (테이블처럼!) 폭발 기능을 시도했지만 정확히 원하는 것을 얻지 못했습니다.

<Reports>
<Report ID="1">
<Locations>
  <Location ID="20001">
    <LocationName>Irvine Animal Shelter</LocationName>
  </Location>   
  <Location ID="20002">
    <LocationName>Irvine City Hall</LocationName>
  </Location>   
  </Locations>
</Report>
<Report ID="2">
<Locations>
  <Location ID="10001">
    <LocationName>California Fish Grill</LocationName>
  </Location>   
  <Location ID="10002">
    <LocationName>Fukada</LocationName>
  </Location>   
  </Locations>
</Report>
</Reports>

상위 수준의 Report.Id를 쿼리 한 다음 하위 (위치 / 위치)의 ID와 이름을 쿼리합니다. 다음은 모든 가능한 조합의 직교 좌표 곱을 제공합니다 (이 예에서는 4 개의 대신 4 개의 행이 필요합니다).

SELECT xpath_int(xml, '/Reports/Report/@ID') AS id, location_id, location_name 
FROM   xmlreports 
LATERAL VIEW explode(xpath(xml, '/Reports/Report/Locations/Location/@ID')) myTable1 AS location_id 
LATERAL VIEW explode(xpath(xml, '/Reports/Report/Locations/Location/LocationName/text()')) myTable2 AS location_name;

구조체로 그룹화하려고 시도한 다음 분해합니다. 그러나이 구조체는 두 개의 행과 두 개의 배열을 반환합니다.

SELECT id, loc.col1, loc.col2
FROM (
SELECT xpath_int(xml, '/Reports/Report/@ID') AS id, 
       array(struct(xpath(xml, '/Reports/Report/Locations/Location/@ID'), xpath(xml,     '/Reports/Report/Locations/Location/LocationName/text()'))) As foo
FROM   xmlreports) x
LATERAL VIEW explode(foo) exploded_table as loc;

결과

1   ["20001","20002"]       ["Irvine Animal Shelter","Irvine City Hall"]
2   ["10001","10002"]       ["California Fish Grill","Irvine Spectrum"]

우리가 원하는 것

1   "20001" "Irvine Animal Shelter"
1   "20002" "Irvine City Hall"
2   "10001" "California Fish Grill"
2   "10002" "Irvine Spectrum"

일반적인 일처럼 보이기를 원하지만 어떤 사례도 찾을 수 없습니다. 어떤 도움이라도 대단히 감사하겠습니다.

해결법

  1. ==============================

    1.이 문제를 해결하는 두 가지 방법이 있습니다.

    이 문제를 해결하는 두 가지 방법이 있습니다.

    subselect를 사용하여 솔루션 2를 구현했습니다. subselects를 사용할 때조차도 Hive는이 작업을 위해 하나의 map-reduce 작업 만 만들 정도로 충분히 똑똑하기 때문에 성능 문제가 발생하지 않을 것이라고 생각합니다.

    SELECT 
     l2.key,
     l2.rid,
     l2.location_id,
     location_name
    FROM (
     SELECT 
      l1.key as key,  
      l1.rid as rid, 
      location_id as location_id,
      l1.xml as xml
     FROM (
       SELECT key, xml, rid
       FROM xmlreports
       LATERAL VIEW explode(xpath(xml, '/Reports/Report/@ID')) rids as rid
     ) l1
     LATERAL VIEW explode(xpath(l1.xml, concat('/Reports/Report[@ID = ',l1.rid, ']/Locations/Location/@ID'))) locids as location_id
    ) l2
    LATERAL VIEW explode(xpath(l2.xml, concat('/Reports/Report[@ID = ',l2.rid, ']/Locations/Location[@ID = ', l2.location_id ,' ]/LocationName/text()'))) locnames as location_name;
    

    제공 한 XML 파일에서이 쿼리를 실행하면 검색 결과가 나타납니다.

    1   1   20001   Irvine Animal Shelter
    1   1   20002   Irvine City Hall
    1   2   10001   California Fish Grill
    1   2   10002   Fukada
    

    희망이 당신의 문제를 해결합니다.

    문안 인사, 디노

  2. from https://stackoverflow.com/questions/15375031/exploding-a-row-of-xml-data-in-hive by cc-by-sa and MIT license