web-dev-qa-db-fra.com

Encodeur pour le type de ligne Spark Datasets

Je voudrais écrire un encodeur pour un type Row dans DataSet, pour une opération de carte que je fais. Essentiellement, je ne comprends pas comment écrire des encodeurs.

Voici un exemple d'une opération de carte:

In the example below, instead of returning Dataset<String>, I would like to return Dataset<Row>

Dataset<String> output = dataset1.flatMap(new FlatMapFunction<Row, String>() {
            @Override
            public Iterator<String> call(Row row) throws Exception {

                ArrayList<String> obj = //some map operation
                return obj.iterator();
            }
        },Encoders.STRING());

Je comprends qu'au lieu d'une chaîne, l'encodeur doit être écrit comme suit:

    Encoder<Row> encoder = new Encoder<Row>() {
        @Override
        public StructType schema() {
            return join.schema();
            //return null;
        }

        @Override
        public ClassTag<Row> clsTag() {
            return null;
        }
    };

Cependant, je ne comprends pas le clsTag () dans l'encodeur, et j'essaie de trouver un exemple en cours d'exécution qui peut démontrer quelque chose de similaire (c'est-à-dire un encodeur pour un type de ligne)

Modifier - Ce n'est pas une copie de la question mentionnée: erreur d'encodeur lors de la tentative de mappage de la ligne de trame de données à la ligne mise à jour comme la réponse parle d'utiliser Spark 1.x dans Spark 2.x (je ne le fais pas), je recherche également un encodeur pour une classe Row plutôt que de résoudre une erreur. Enfin, je cherchais une solution en Java, pas à Scala.

23
tsar2512

La réponse est d'utiliser un RowEncoder et le schéma de l'ensemble de données en utilisant StructType .

Vous trouverez ci-dessous un exemple de travail d'une opération de flatmap avec des ensembles de données:

    StructType structType = new StructType();
    structType = structType.add("id1", DataTypes.LongType, false);
    structType = structType.add("id2", DataTypes.LongType, false);

    ExpressionEncoder<Row> encoder = RowEncoder.apply(structType);

    Dataset<Row> output = join.flatMap(new FlatMapFunction<Row, Row>() {
        @Override
        public Iterator<Row> call(Row row) throws Exception {
            // a static map operation to demonstrate
            List<Object> data = new ArrayList<>();
            data.add(1l);
            data.add(2l);
            ArrayList<Row> list = new ArrayList<>();
            list.add(RowFactory.create(data.toArray()));
            return list.iterator();
        }
    }, encoder);
24
tsar2512

J'ai eu le même problème ... Encoders.kryo(Row.class)) a fonctionné pour moi.

En prime, les documents de réglage Apache Spark font référence à Kryo car il est plus rapide à la sérialisation "souvent jusqu'à 10x":

https://spark.Apache.org/docs/latest/tuning.html

5
Jim Bob