Чтение 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,

  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, если вы определяете для них схему, то только 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, чтобы соединить их вместе, вот что вы хотите сделать.

Другие вопросы по тегам