0

我想将具有 3 个不同 RowTag 的巨大 XML 文件读入 Apache Spark 数据帧。

RowTag = XML 元素,您在 Spark 中将其解释为一行。

标签

  • 包含不同的数据结构
  • 不重叠

xml-spark ( https://github.com/databricks/spark-xml ) 只提供一次读取一个 RowTag,所以我需要读取相同的文件 3 次(效率不高)。

有没有办法一次读取文件?

细节:

我有一个巨大的 XML 文件(24 GB),其中包含 3 个列表:

<myFile>
    <ContainedResourceList>
        <SoundRecording><Title>A</Title></SoundRecording>
      ... several million records ...
        <SoundRecording><Title>Z</Title></SoundRecording>
    </ContainedResourceList>

    <ContainedReleaseList>
        <Release><ReleaseType>Single</ReleaseType></Release>
      ... several million records ...
        <Release><ReleaseType>LP</ReleaseType></Release>
    </ContainedReleaseList>

    <ContainedTransactionList>
        <Transaction><Sales>1</Sales></Transaction>
      ... several million records ...
        <Transaction><Sales>999</Sales></Transaction>
    </ContainedTransactionList>
</myFile>

XML 文件有效。我想阅读 RowTags SoundRecording、Release & Transaction。

我更喜欢 Scala 库,但我会为任何支持读取的库感到高兴。

PS: 输出和他的模式如何?

  • 最佳选择:3 个 DataFrame 的数组,每个 RowTag 一个
  • 丑陋的选项:一个包含所有 3 个数据结构的可能元素的 DataFrame
4

3 回答 3

0

根据我对 spark-xml 的使用,我知道它需要 XML 文件中有 2 个标签,

  1. 根标签

  2. 行标签

您的输入文件应如下所示,

<root>
    <row>
        <FirstField> abc </FirstField>
        <SecondField> def <SecondField>
    </row>
    <row>
        <FirstField> ghi </FirstField>
        <SecondField> jkl <SecondField>
    </row>
    .
    .
    <row>
        <FirstField> uvw </FirstField>
        <SecondField> xyz <SecondField>
    </row>
</root>

并阅读上面的文件,语法是

spark-shell --packages com.databricks:spark-xml_2.11:0.5.0
import com.databricks.spark.xml._
import org.apache.spark.sql.types._
val schema = StructType(List(StructField("FirstField",StringType,true),StructField("SecondField",StringType,true)))
val df = spark.read.option("rootTag","root").option("rowTag","row").schema(schema)xml("pathToFile")

在您的情况下,您有一个 rootTag 作为“myFile”,但现在有行标签。因此,您可以尝试使用“myFile”作为 rowTag,关键是您必须按如下方式创建架构,

val schema = StructType(List(StructField("ContainedResourceList",StringType,true),StructField("ContainedReleaseList",StringType,true),StructField("ContainedTransactionList",StringType,true)))

然后读取文件,

 val df = spark.read.option("myFile","row").schema(schema).xml("pathToFile")

现在你可以处理这个 df

你有 SoundRecording、Release 和 Transaction 的重复标签,如果你为这些定义模式,那么只有重复中的第一个值被解析,<Title>A</Title>, <ReleaseType>Single</ReleaseType>, <Sales>1</Sales>在你的情况下。

我还没有弄清楚如何解析 Spark-xml 中的重复标签

于 2019-03-11T05:37:43.307 回答
0

将 myfile 读取为行标记将产生一个 HUGE 行,然后爆炸成行将由一个 spark 工作人员完成。

您可以将它们读入 3 个不同的数据框,指定不同的行标签,因为每个都有不同的架构。这将导致 3 个不同的数据帧,每个数据帧都有数百万行,这将通过 spark 更有效地工作。

为了加快处理速度,您可以将 xml 文件预先拆分为多个块,甚至进一步拆分为 3 组文件(将XML 文件拆分为多个给定标签)。这样,工人可以并行读取多个部分,当他们完成一个部分时,他们可以移动到下一个部分。否则,只有一名工作人员必须按顺序读取文件并使用它自己的分区方式并将它们分发给工作人员。

然后你可以使用 spark-sql 将它们连接在一起,这就是你想要做的。

于 2019-04-02T00:40:57.760 回答
0

一种简单的方法是使用explode 函数。您可以读取将 rowTag 设置为 ContainedResourceList 的完整 xml,然后使用生成的数据框用新列分解数据框

df.withColumn("soundRec", explode($"SoundRecording"))

您可以为要爆炸的每个标签添加多个列

于 2017-08-19T16:10:25.003 回答