Выберите поля, которые начинаются с определенного шаблона: Spark XML Parsing
Я должен разобрать некоторые очень большие файлы 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 ответ
Ты можешь использовать .*
чтобы выделить все элементы столбца значений в отдельные столбцы, отфильтруйте все имена элементов, начинающиеся с 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):_*)
который должен дать вам все элементы столбца структуры значений, который начинается с E2EDK1
как отдельные столбцы. Для вашего данного примера вы должны иметь вывод
+---------+
|E2EDK1000|
+---------+
|null |
+---------+
root
|-- E2EDK1000: string (nullable = true)
Вы можете объединить их обратно struct
если вы хотите