Преобразование Spark DF в DS с разными именами полей

#java #apache-spark #apache-spark-sql #pojo #apache-spark-dataset

Вопрос:

Я хочу преобразовать фрейм данных Spark в набор данных POJO с разными именами полей. У меня есть фрейм данных полей: name , date_of_birth , где их типы StringType , DateType .

И POJO из:

 public class Person implements Serializable {
    private String name;
    private Date dateOfBirth;
}
 

Я успешно конвертирую его в dataset с помощью следующего кода:

 Encoder<Person> personEncoder =  Encoders.bean(Person.class); 
Dataset<Person> personDS = result.as(personEncoder);
List<Person> personList = personDS.collectAsList();
 

Только если я перед этим изменю имена столбцов фрейма данных на имена пользователя POJO. Есть ли какой-либо способ указать Spark для сопоставления между полями со стороны POJO?

Я думал о Gson @SerializedName(“date_of_birth”) , но это ни на что не повлияло.

Ответ №1:

Если у вас есть сопоставление имен, скажем, на карте, вы можете использовать его для переименования столбцов перед преобразованием фрейма данных в набор данных.

Это может быть написано так:

 // I create the map, but it could be read from a config file for instance
Map<String, String> nameMapping = new java.util.HashMap<>();
nameMapping.put("id", "name");
nameMapping.put("date", "dateOfBirth");

Column[] renamedColumns = nameMapping
                .entrySet()
                .stream()
                .map(x -> col(x.getKey()).alias(x.getValue()))
                .collect(Collectors.toList())
                .toArray(new Column[0]);

result.select(renamedColumns).as(personEncoder)
 

Ответ №2:

Я не знаю конкретных аннотаций. Однако вот как я бы это решил.

Я бы создал определенный фрейм данных с нужной мне формой, а затем экспортировал его.

Это будет выглядеть так:

 Dataset<Row> exportDf = df
    .withColumn("dateOfBirth",
        col("date_of_birth").cast(DataTypes.StringType))
    .drop("date_of_birth");
 

Полный пример, который я написал, можно найти здесь: https://github.com/jgperrin/net.jgp.labs.spark/tree/master/src/main/java/net/jgp/labs/spark/l999_scrapbook/l002.

Примечания:

  • Я предполагаю, что result в вашем коде есть Dataset<Row> .
  • Я использовал строку для вашей даты, так как Spark немного беспокоился о преобразовании даты в строку в POJO. Если вам нужна помощь конкретно по этому вопросу, создайте еще один вопрос SO, я с радостью рассмотрю его.

Комментарии:

1. Спасибо за усилия! Это решение не совсем подходит, потому что я хочу, чтобы преобразование было динамическим, чтобы я мог добавить столбец и поле для DF и POJO, и это будет работать, не касаясь кода преобразования.

2. Я понимаю … будьте осторожны с типами данных, они могут обмануть вас при преобразовании … особенно даты!