Чтение XML-файла в Spark с несколькими RowTags
Я хотел бы прочитать огромный XML-файл с 3 различными тегами RowTag в Apache Spark Dataframes.
RowTag = Элемент XML, который вы интерпретируете как строку в Spark.
Теги
- содержат разные структуры данных
- не перекрываются
xml-spark ( https://github.com/databricks/spark-xml) предлагает только чтение одного RowTag за раз, поэтому мне нужно будет читать один и тот же файл 3 раза (не эффективно).
Есть ли способ прочитать файл за одно чтение?
Подробности:
У меня есть огромный XML-файл (24 ГБ), который содержит 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 libs, но я был бы рад за любую библиотеку, позволяющую читать.
PS: Как может выглядеть выход и его схема?
- Лучший вариант: массив из 3-х DataFrames, по одному на каждый RowTag
- Гадкий вариант: один DataFrame, содержащий возможные элементы всех 3 структур данных
1 ответ
Из моего использования spark-xml я понимаю, что он ожидает 2 тега в файле XML,
корневой тег
тег строки
и ваш входной файл должен выглядеть примерно так:
<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, если вы определяете для них схему, то только 1-е значение среди повторения получает анализ, который <Title>A</Title>, <ReleaseType>Single</ReleaseType>, <Sales>1</Sales>
в твоем случае.
Мне еще предстоит выяснить, как разобрать повторяющиеся теги в Spark-xml
Одним простым способом является использование функции разнесения. Вы можете прочитать полный XML-файл с rowTag, установленным в ContainedResourceList, а затем с результирующим фреймом данных взорвать фрейм данных с новым столбцом.
df.withColumn("soundRec", explode($"SoundRecording"))
Вы можете добавить несколько столбцов для каждого тега, который вы хотите взорвать
Считывание myfile в качестве тега строки приведет к получению одной ОГРОМНОЙ строки, а затем один работник, работающий со свечами, выполнит разрыв в строки.
Вы можете прочитать их в 3 разных фреймах данных, указав разные метки строк, потому что каждый из них имеет свою схему. Это привело бы к 3 различным фреймам данных, каждый с миллионами строк, который работал бы более эффективно с помощью искры.
Для ускорения обработки вы можете предварительно разбить XML-файл на несколько кусков и даже далее на 3 набора файлов ( разделение XML-файла на несколько по заданным тегам). Таким образом, работники могут читать несколько частей параллельно, а когда они заканчивают с одной частью, они могут переходить к следующей части. В противном случае только один работник должен будет последовательно прочитать файл и использовать его для разделения и передачи их работникам.
Затем вы можете использовать spark-sql, чтобы соединить их вместе, вот что вы хотите сделать.