Выберите поля, которые начинаются с определенного шаблона: Spark XML Parsing - PullRequest
0 голосов
/ 13 июня 2018

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

Вот пример того, чего я пытаюсь достичь:

// Some made up data
val schema = new StructType()
      .add("devices", 
        new StructType()
          .add("thermostats", MapType(StringType,
            new StructType()
              .add("device_id", StringType)
              .add("locale", StringType)
              .add("E2EDK1000", StringType)
              .add("E2EDK2000", StringType)
              .add("E2EDK3000", StringType))))

val nestDataDS2 = Seq("""{
    "devices": {
      "thermostats": {
          "peyiJNo0IldT2YlIVtYaGQ": {
            "device_id": "peyiJNo0IldT2YlIVtYaGQ",
            "locale": "en-US",
            "E2EDK1000": "4.0",
            "E2EDK2000": "VqFabWH21nwVyd4RWgJgNb292wa7hG_dUwo2i2SG7j3-BOLY0BA4sw",
            "E2EDK3000": "Hallway Upstairs"}}}}""").toDS
val nestDF2 = spark
            .read
            .schema(nestSchema2)
            .json(nestDataDS2.rdd)

root
 |-- devices: struct (nullable = true)
 |    |-- thermostats: map (nullable = true)
 |    |    |-- key: string
 |    |    |-- value: struct (valueContainsNull = true)
 |    |    |    |-- device_id: string (nullable = true)
 |    |    |    |-- locale: string (nullable = true)
 |    |    |    |-- E2EDK1000: string (nullable = true)
 |    |    |    |-- E2EDK2000: string (nullable = true)
 |    |    |    |-- E2EDK3000: string (nullable = true)

Учитывая это, я хочу получить значение поля, поэтому я делаю следующее

val tmp = nestDF2.select($"devices.thermostats.value")
root
 |-- value: struct (nullable = true)
 |    |-- device_id: string (nullable = true)
 |    |-- locale: string (nullable = true)
 |    |-- E2EDK1000: string (nullable = true)
 |    |-- E2EDK2000: string (nullable = true)
 |    |-- E2EDK3000: string (nullable = true)

Вот моя проблема: я хочу выбрать все поля в пределах значения, которые начинаются со следующего шаблона E2EDK1.Тем не менее, я застрял на том, как это сделать.Вот конечный результат, который мне нужен:

root
 |-- E2EDK1000: string (nullable = true)

Я знаю, что могу выбрать это поле сразу, но в данных, с которыми я работаю, это не всегда тот случай, когда E2EDK1000 всегда будет там.Там всегда будет E2EDK1.

Я пытался использовать startWith (), но это не работает, например,

val tmp2 = tmp
  .select($"value".getItem(_.startsWith("E2EDK1")))

1 Ответ

0 голосов
/ 13 июня 2018

Вы можете использовать .*, чтобы выделить все элементы столбца значения в отдельные столбцы, отфильтровать все имена элементов, которые начинаются с E2EDK1, и, наконец, выбрать только эти столбцы, как показано ниже

//flattens the struct value column to separate columns
val tmp = nestDF2.select($"devices.thermostats.value.*")
//filter in the column names that starts with E2EDK1
val e2edk1Columns = tmp.columns.filter(_.startsWith("E2EDK1"))
//select only the columns that starts with E2EDK1
tmp.select(e2edk1Columns.map(col):_*)

который должен дать вам все элементы значение struct column , которое начинается с E2EDK1 как отдельные столбцы.Для вашего данного примера вы должны иметь вывод

+---------+
|E2EDK1000|
+---------+
|null     |
+---------+

root
 |-- E2EDK1000: string (nullable = true)

Вы можете объединить их обратно в struct, если хотите

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...