Идея состоит в том, чтобы использовать case-классы , чтобы преобразовать вложенную структуру в набор простых классов Scala, которые проще обрабатывать - или в терминах Spark: использовать (типизированный) Dataset вместо нетипизированного DataFrame.
case class Phone(var PhoneNum:String)
case class Apt(Apt:String)
case class Person(Name: String, Age: Long, Address:Array[Apt], Phone:Array[Phone])
case class Register(Persons:Array[Person])
case class TopLevel(Register:Register)
Преобразование кадра данных в набор данных и затем применение вызова map
к каждой записи набора данных:
val df = ...
val ds = df.as[TopLevel]
val transformed = ds.map(tl => {
for( p <- tl.Register.Persons) {
if(p.Address.contains(Apt("Apt1"))) p.Phone.transform(_ => Phone("7777"))
}
tl
})
transformed.toJSON.show(false)
отпечатков:
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|value |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|{"Register":{"Persons":[{"Name":"Name1","Age":12,"Address":[{"Apt":"Apt1"}],"Phone":[{"PhoneNum":"7777"}]},{"Name":"Name2","Age":14,"Address":[{"Apt":"Apt2"}],"Phone":[{"PhoneNum":"55555"}]}]}}|
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Замечание по структуре / схеме данных в вопросе :
В ответ на вопрос используется рамка данных регистров.Это означает, что каждая запись в кадре данных содержит один регистр.Было бы более интуитивно понятно, если бы информационный блок содержал список лиц и этот список людей назывался «Регистр».Это привело бы к гораздо более легкой структуре данных.В этом случае классы TopLevel
и Register
могут быть опущены.