【问题标题】:Loading XML file to Hive tables将 XML 文件加载到 Hive 表
【发布时间】:2018-11-08 23:31:24
【问题描述】:

我们正在努力在 Hive 表中加载一个半结构化的 XML 文件。这些是零售购买数据。
我附上了一个示例 XML 文件以了解数据的外观以及我用来读取该 XML 文件的 Hive 表定义。

该文件在 XML 中的每个篮子的“Tender”下有多个 Payment 和 Amount(Amt) 部分。例如,客户可以通过现金、EFTPOS、信用卡、忠诚卡或有时使用这些组合来支付。

从附加的 XML 读取数据时,结果显示 Payment 列与 XML 中的条目合并,对于“Amt”,它显示为 NULL。

我知道我用来读取数据的表格不是 100% 正确的。
请告诉我如何使用 xpath 函数为相同的元素名称“Payment”和“Amt”创建多个记录

我试图在互联网上找到一些相同的文档,但找不到与我的场景相似的任何内容。

样本数据:

<Bskt>
  <TillNo>4</TillNo>
  <BsktNo>1747</BsktNo>
  <DateTime>2017-10-31T10:51:25.000+11:00</DateTime>
  <OpID>10115</OpID>
  <Tender>
    <PayType>CSH</PayType>
    <Amt>46.75</Amt>
  </Tender>
  <Tender>
    <PayType>ITMLOY</PayType>
    <Amt>0</Amt>
    <CardNo>2679911927</CardNo>
    <Program>SmartRewards</Program>
    <Earn>46.00</Earn>
    <Burn>0.00</Burn>
  </Tender>
</Bskt>
<Bskt>
  <TillNo>4</TillNo>
  <BsktNo>1748</BsktNo>
  <DateTime>2017-10-31T10:53:11.000+11:00</DateTime>
  <OpID>10115</OpID>
  <Tender>
    <PayType>CSH</PayType>
    <Amt>46.75</Amt>
  </Tender>
  <Tender>
    <PayType>ITMLOY</PayType>
    <Amt>0</Amt>
    <CardNo>2619183833</CardNo>
    <Program>SmartRewards</Program>
    <Earn>46.00</Earn>
    <Burn>0.00</Burn>
  </Tender>
</Bskt>
<Bskt>
  <TillNo>4</TillNo>
  <BsktNo>1753</BsktNo>
  <DateTime>2017-10-31T11:19:34.000+11:00</DateTime>
  <OpID>50056</OpID>
  <Tender>
    <PayType>CSH</PayType>
    <Amt>28.10</Amt>
  </Tender>
  <Tender>
    <PayType>ITMLOY</PayType>
    <Amt>0</Amt>
    <CardNo>8263734549</CardNo>
    <Program>SmartRewards</Program>
    <Earn>28.00</Earn>
    <Burn>0.00</Burn>
  </Tender>
</Bskt>

蜂巢表:

CREATE EXTERNAL TABLE BASKET_TENDER (
`DateTime` string,
`BsktNo` double,
`TillNo` int,
`PayType` string,
`Amt` float,
`CardNo` string,
`Program` string,
`Earn` float,
`Burn` float
)

ROW FORMAT SERDE 'com.ibm.spss.hive.serde2.xml.XmlSerDe'
WITH SERDEPROPERTIES (

"column.xpath.DateTime"="/Bskt/DateTime/text()",
"column.xpath.BsktNo"="/Bskt/BsktNo/text()",
"column.xpath.TillNo"="/Bskt/TillNo/text()",
"column.xpath.PayType"="/Bskt/Tender/Paytype/text()",
"column.xpath.CardNo"="/Bskt/Tender/CardNo/text()",
"column.xpath.Amt"="/Bskt/Tender/Amt/text()",
"column.xpath.Program"="/Bskt/Tender/Program/text()",
"column.xpath.Earn"="/Bskt/Tender/Earn/text()",
"column.xpath.Burn"="/Bskt/Tender/Burn/text()"
)

STORED AS INPUTFORMAT 'com.ibm.spss.hive.serde2.xml.XmlInputFormat'
    OUTPUTFORMAT 
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat' 
    LOCATION '<hdfs file location>'
    TBLPROPERTIES (
    "xmlinput.start"="<Bskt","xmlinput.end"="</Bskt>"
);

Hive 查询输出:

select * from BASKET_TENDER

【问题讨论】:

  • /Paytype/text() 上的错字...
  • 因此,每个&lt;Bskt&gt; 都有两个可能的/Bskt/Tender/ 路径。你如何让 Hive 知道它需要解析哪一个?
  • 已更正错字。甚至我的困惑也是一样的。在我的情况下,我如何让 Hive 知道它需要解析哪一个,其中每个“Bskt”都有两个“Tender”,元素“Payment”和“Amt”的名称相同。
  • 我需要实现以下任一目标:1) 使用相同的篮子详细信息为第二次招标创建另一行。或 2) 创建另一个名为“Payment_Loyalty”和“Amt_Loyalty”的列,并在那里加载第二个投标详细信息。我想知道如何实现这两种解决方案。

标签: xml parsing hadoop xpath hive


【解决方案1】:

只获取一个字段

您可以使用下标运算符 ([]) 来解析 xml。但是,请确保索引以 1 而不是 0 开头。

在您的情况下,我假设您想要第二次招标。然后只需使用以下 xml 路径。

"column.xpath.PayType"="/Bskt/Tender[2]/PayType/text()",
"column.xpath.CardNo"="/Bskt/Tender[2]/CardNo/text()",
"column.xpath.Amt"="/Bskt/Tender[2]/Amt/text()",

这将为您提供以下值。

获取两个字段

如果要将两个字段都作为数组的一部分,则需要将这些字段定义为数组,并且在选择xpath时不提供任何下标运算符,如下所述

drop table temp.BASKET_TENDER;
CREATE EXTERNAL TABLE temp.BASKET_TENDER (
`DateTime` string,
`BsktNo` double,
`TillNo` int,
`PayType`  array<String>,
`Amt` array<float>,
`CardNo` array<string>,
`Program` string,
`Earn` float,
`Burn` float
)

ROW FORMAT SERDE 'com.ibm.spss.hive.serde2.xml.XmlSerDe'
WITH SERDEPROPERTIES (

"column.xpath.DateTime"="/Bskt/DateTime/text()",
"column.xpath.BsktNo"="/Bskt/BsktNo/text()",
"column.xpath.TillNo"="/Bskt/TillNo/text()",
"column.xpath.PayType"="/Bskt/Tender/PayType/text()",
"column.xpath.CardNo"="/Bskt/Tender/CardNo/text()",
"column.xpath.Amt"="/Bskt/Tender/Amt/text()",
"column.xpath.Program"="/Bskt/Tender/Program/text()",
"column.xpath.Earn"="/Bskt/Tender/Earn/text()",
"column.xpath.Burn"="/Bskt/Tender/Burn/text()"
)

STORED AS INPUTFORMAT 'com.ibm.spss.hive.serde2.xml.XmlInputFormat'
    OUTPUTFORMAT 
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat' 
    LOCATION '/tmp/BASKET_TENDER'
    TBLPROPERTIES (
    "xmlinput.start"="<Bskt","xmlinput.end"="</Bskt>"
);

select * from temp.BASKET_TENDER;

输出将如前所述打击

【讨论】:

  • 是否可以让 XPATH 填充 Hive 数组字段?
  • 是的,在这种情况下,您可能需要将字段作为数组
  • 非常感谢 Gaurang.. 它解决了我的问题。但是上面提供的选项可以正常工作:)
  • HI Gaurang.. 你能帮我解决我的问题吗:stackoverflow.com/questions/53384728/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多