Select 以特定模式开头的字段:Spark XML 解析
Select Fields that start with a certain pattern: Spark XML Parsing
我不得不解析一些非常大的 xml 文件。我想提取这些 xml 文件中的几个字段,然后对它们执行一些操作。但是,我需要遵循一些规则,即如果它们遵循特定模式,我只能 select 个字段。
这是我正在努力实现的示例:
// 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)
这是我的问题:我想 select value 中以以下模式 E2EDK1 开头的所有字段。但是,我坚持如何做到这一点。这是我想要的最终结果:
root
|-- E2EDK1000: string (nullable = true)
我知道我可以 select 那个领域,但在我处理的数据中,E2EDK1000 并不总是存在的。永远存在的是 E2EDK1。
我试过使用 startsWith() 但这似乎不起作用,例如
val tmp2 = tmp
.select($"value".getItem(_.startsWith("E2EDK1")))
可以使用.*
将value列的所有元素select分到单独的列中,过滤掉所有以E2EDK1
开头的元素名,最后过滤掉select只有那些列如下
//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
开头的 value struct column 的所有元素作为单独的列。对于给定的示例,您应该输出
+---------+
|E2EDK1000|
+---------+
|null |
+---------+
root
|-- E2EDK1000: string (nullable = true)
如果需要,您可以将它们组合回 struct
我不得不解析一些非常大的 xml 文件。我想提取这些 xml 文件中的几个字段,然后对它们执行一些操作。但是,我需要遵循一些规则,即如果它们遵循特定模式,我只能 select 个字段。
这是我正在努力实现的示例:
// 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)
这是我的问题:我想 select value 中以以下模式 E2EDK1 开头的所有字段。但是,我坚持如何做到这一点。这是我想要的最终结果:
root
|-- E2EDK1000: string (nullable = true)
我知道我可以 select 那个领域,但在我处理的数据中,E2EDK1000 并不总是存在的。永远存在的是 E2EDK1。
我试过使用 startsWith() 但这似乎不起作用,例如
val tmp2 = tmp
.select($"value".getItem(_.startsWith("E2EDK1")))
可以使用.*
将value列的所有元素select分到单独的列中,过滤掉所有以E2EDK1
开头的元素名,最后过滤掉select只有那些列如下
//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
开头的 value struct column 的所有元素作为单独的列。对于给定的示例,您应该输出
+---------+
|E2EDK1000|
+---------+
|null |
+---------+
root
|-- E2EDK1000: string (nullable = true)
如果需要,您可以将它们组合回 struct