We have a Kafka stream that has headers enabled
.option("includeHeaders", true)
thus making them stored as a high level dataset's colum, bearing the inside array of structs with key and value:
root
|-- topic: string (nullable = true)
|-- key: string (nullable = true)
|-- value: string (nullable = true)
|-- timestamp: string (nullable = true)
|-- headers: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- key: string (nullable = true)
| | |-- value: binary (nullable = true)
I can access the needed header with it's order in the array like that:
val controlDataFrame = spark
.readStream
.format("kafka")
.option("kafka.bootstrap.servers", kafkaLocation)
.option("includeHeaders", true)
.option("failOnDataLoss", value = false)
.option("subscribe", "mytopic")
.load()
.withColumn("acceptTimestamp", element_at(col("headers"),1))
.withColumn("acceptTimestamp2", col("acceptTimestamp.value").cast("STRING"))
but this solution looks fragile, as the order of headers produced on other side can always be changed with updates, while only thhe key name looks stabile there. How can I lookup through the struct keys and extract the needed struct rather than poin the array index?
UPD.
Thanks to davice of Alex Ott, I have fount the solution to get what I want into the following columns:
.withColumn("headers1", map_from_entries(col("headers")))
.withColumn("acceptTimestamp2", col("headers1.acceptTimestamp").cast("STRING"))