Я не могу найти именно то, что я ищу, поэтому вот мой вопрос. Я извлекаю из MongoDb некоторые данные в Spark Dataframe. Фрейм данных имеет следующую схему (df.printSchema
):
|-- flight: struct (nullable = true)
| |-- legs: array (nullable = true)
| | |-- element: struct (containsNull = true)
| | | |-- arrival: timestamp (nullable = true)
| | | |-- departure: timestamp (nullable = true)
| |-- segments: array (nullable = true)
| | |-- element: struct (containsNull = true)
| | | |-- arrival: timestamp (nullable = true)
| | | |-- departure: timestamp (nullable = true)
Обратите внимание на структуру верхнего уровня, за которой следует массив, внутри которого мне нужно изменить свои данные. Например:
{
"flight": {
"legs": [{
"departure": ISODate("2020-10-30T13:35:00.000Z"),
"arrival": ISODate("2020-10-30T14:47:00.000Z")
}
],
"segments": [{
"departure": ISODate("2020-10-30T13:35:00.000Z"),
"arrival": ISODate("2020-10-30T14:47:00.000Z")
}
]
}
}
Я хочу экспортировать это в Json, но по какой-то деловой причине я хочу, чтобы даты прибытия имели другой формат, чем даты отъезда. Например, я могу экспортировать ISODate отправления в мс из эпохи, но не прибытия.
Для этого я подумал о применении пользовательской функции для преобразования:
// Here I can do any tranformation. I hope to replace the timestamp with the needed value
val doSomething: UserDefinedFunction = udf( (value: Seq[Timestamp]) => {
value.map(x => "doSomething" + x.getTime) }
)
val newDf = df.withColumn("flight.legs.departure",
doSomething(df.col("flight.legs.departure")))
Но это просто возвращает совершенно новый столбец, содержащий массив из одной строки doSomething
.
{
"flight": {
"legs": [{
"arrival": "2020-10-30T14:47:00Z",
"departure": "2020-10-30T13:35:00Z"
}
],
"segments": [{
"arrival": "2020-10-30T14:47:00Z",
"departure": "2020-10-30T13:35:00Z",
}
]
},
"flight.legs.departure": ["doSomething1596268800000"]
}
И newDf.show(1)
+--------------------+---------------------+
| flight|flight.legs.departure|
+--------------------+---------------------+
|[[[182], 94, [202...| [doSomething15962...|
+--------------------+---------------------+
Вместо
{
...
"arrival": "2020-10-30T14:47:00Z",
//leg departure date that I changed
"departure": "doSomething1596268800000"
... // segments not affected in this example
"arrival": "2020-10-30T14:47:00Z",
"departure": "2020-10-30T13:35:00Z",
...
}
Есть идеи, как поступить?
Редактировать - уточнение : Имейте в виду, что моя схема намного сложнее, чем показанная выше. Например, есть еще один тег data
верхнего уровня, поэтому flight
ниже вместе с другой информацией. Затем внутри flight
, legs
и segments
есть еще несколько элементов, некоторые из которых также являются вложенными. Я сосредоточился только на тех, что мне нужно было изменить.
Я говорю это, потому что я хотел бы самое простое решение, которое будет масштабироваться. Т.е. в идеале тот, который просто изменил бы требуемые элементы без необходимости деконструкции, и перестроил бы всю вложенную структуру. Если мы не можем избежать этого, является ли использование case-классов самым простым решением?