我想在Apache Spark Dataframes中读取一个包含3个不同RowTag的巨大XML文件。
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&amp;事务。
我更喜欢Scala libs,但我会很高兴任何启用了读取的lib。
PS: 输出和输出怎么样?他的架构看起来像?
答案 0 :(得分:0)
一种简单的方法是使用爆炸功能。您可以将rowTag设置为ContainedResourceList读取完整的xml,然后使用生成的数据框将数据框分解为新列
df.withColumn("soundRec", explode($"SoundRecording"))
您可以为要爆炸的每个标记添加多个列
答案 1 :(得分:0)
根据我对spark-xml的使用,我了解它期望XML文件中有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中的重复标签
答案 2 :(得分:0)
将myfile作为行标记读取将导致巨大的一行,然后由一个spark工作者将其爆炸成行。
您可以将它们读取到3个不同的数据帧中,以指定不同的行标签,因为每个行都有不同的架构。这将导致3个不同的数据帧,每个数据帧具有数百万行,通过spark可以更有效地工作。
要加快处理速度,您可以将xml文件预先分成多个块,甚至可以进一步分成3组文件(Splitting XML file into multiple at given tags)。这样,工人可以并行读取多个部分,当他们完成一个部分时,可以移至下一个部分。否则,只有一名工作人员将必须顺序读取文件,并使用其自己的分区方式将其分发给工作人员。
然后,您可以使用spark-sql将它们连接在一起,这就是您想要做的事情。