Вложенные XML данные AWS Клей - PullRequest
0 голосов
/ 29 мая 2020

У нас есть данные в этом формате:

<doc>
  <event timestamp="20200529032100">
    <row attr="test" id="3">data</row>
    <row attr="gfds" id="6">data</row>
    <row attr="sadf" id="8">data</row>
  </event>
</doc>

Мы хотим извлечь данные в каждой строке, но одновременно с меткой времени. Мы пытаемся сделать это с помощью задания AWS ETL и CSV в качестве вывода.

Мы попытались добавить классификатор для row, но тогда мы не получили метку времени. Когда мы пытаемся добавить классификатор для event, мы получаем метку времени, но после задания etl поля, извлеченные из строки, отображаются только для событий, содержащих только одну row -запись внутри. Для тех, у которых несколько row -элементов, в результирующем CSV есть только одна строка, а поля, которые мы пытаемся извлечь из row, пусты, вместо того, чтобы получать такое же количество строк csv, как есть row записи, это то, что мы хотим.

Можно ли это решить с помощью AWS Glue, или это то, что мы должны создать сами?

1 Ответ

1 голос
/ 30 мая 2020

У нас была похожая ситуация, и мы не смогли построить таблицу, используя только собственный классификатор. Мы написали задание, которое считывает XML в фрейм данных, используя указанную нами схему, а затем использует метод explode для поворота вложенных элементов в их собственные строки.

Обратите внимание, что вам нужно добавить искру_ xml jar в качестве зависимого jar-файла для вашей работы (или конечной точки разработчика, если вы разрабатываете в блокноте), как описано в https://towardsdatascience.com/use-aws-glue-and-or-databricks-spark-xml-to-process-xml-data-21eaef390fda.

Примерный план того, что вы должны попробовать в вашем задании:

  1. Определите схему для структуры элемента, представляющего строки, которые вы сначала считываете во фрейм данных. В вашем примере, если вам нужна одна строка для каждого события, определите схему для вашего элемента события, которая включает элемент строки как тип массива. Что-то вроде:
    mySchema = StructType(
        [StructField('_timestamp',LongType(),True),
         StructField('row', ArrayType(StructType([StructField('_VALUE', StringType(), True),
                                      StructField('_attr', StringType(), True),
                                      StructField('_id', LongType(), True)]), True), True)])
Прочитать файл XML в фрейм данных, используя схему
    spark_df = spark.read.format("xml").options(rowTag="event").options(nullValue="").schema(mySchema).load("s3://bucket/path/to/xml")
Используйте разнесение для создания нового фрейма данных с одной строкой на тег строки
    row_df = spark_df.withColumn('eachrow', explode(col('row')))

Это даст вам фрейм данных, который выглядит следующим образом:

+--------------+--------------------+-------------+
|    _timestamp|                 row|      eachrow|
+--------------+--------------------+-------------+
|20200529032100|[[data,test,3], [...|[data,test,3]|
|20200529032100|[[data,test,3], [...|[data,gfds,6]|
|20200529032100|[[data,test,3], [...|[data,sadf,8]|
+--------------+--------------------+-------------+
Выберите атрибут отметки времени и атрибут / значения строки.
final_df = row_df.select(col('_timestamp').alias('timestamp'), col('eachrow._VALUE').alias('row_value')...)

Затем вы можете записать фрейм данных в любом нужном вам формате.

...