【Spark SQL】- 自定义结构的DataFrame和 Dataset

1.步骤分析

  • 读取的 people.txt 文件内容
          Michael, 29
          Andy, 30
          Justin, 19  
  • 第一步 读取文件 创建RDD

 // 创建一个RDD
        JavaRDD<String> peopleRDD = spark.sparkContext()
        		// textFile参数 (文件路径 , 切片数)
                .textFile("F:/Code/Spark/SparkSql/SparkSql/src/main/resources/people.txt", 1)
                .toJavaRDD();

  • 第二步 创建DataFrame 的结构

  1. 定义DataFrame 的列名(字段名) 使用空格分隔
    String fieldNames = "name age";
  2. 创建存储字段(每一列)对象的集合
    List<StructField> fields = new ArrayList<>();
  3. 根据列名生成相应的字段对象 , 并存入 fields 集合中
       for (String fieldName : fieldNames.split(" ")) {
           StructField field = DataTypes
                   // 参数 (字段名 , 字段值类型 , 字段值是否可以为空)
                   .createStructField(fieldName, DataTypes.StringType , true);
           // 将创建的字段结构对象存入集合中
           fields.add(field);
       }
  1. // 创建结构类型对象 , 封装了DataFame 所有的列(字段/属性) 的对象
    // 这个对象就代表了 DataFrame的结构
    // createStructType(集合 / 数组) 要求必须是 StructField
    StructType schema = DataTypes.createStructType(fields);
  • 第三步 数据转化

  1. // 将原本RDD中的数据 封装到 ROW 中
    // 原本的数据 : Michael, 29
    // 封装后的数据 : ROW(Michael , 29)
        JavaRDD<Row> rowRDD = peopleRDD.map((Function<String, Row>) lines -> {

            // 对数据进行分割
            String[] attributes = lines.split(",");
            return RowFactory.create(attributes[0], attributes[1].trim());
        });
  1. // 将RDD 转化为 自定义结构的DataFrame
    Dataset<Row> peopleDataFrame = spark.createDataFrame(rowRDD, schema);
  • 第四步 进行简单的测试

 /* 查询数据 */

        // 1.创建临时表
        peopleDataFrame.createOrReplaceTempView("people");

        // 2. 执行Sql 语句进行查询
        Dataset<Row> result = spark.sql("SELECT name FROM people");

        // 3.显示查询结果
        result.show();

        // 将 name 列的数据转化为 Dataset类型的
        // Map的参数 (RDD , 编码器对象)
        Dataset<String> nameDS = result.map(
                // getString(int colIndex)
                (MapFunction<Row, String>) row -> "name:" + row.getString(0),
                Encoders.STRING()
        );

        // 显示数据
        nameDS.show();

2.完整源代码

// 指定 DataFrame 的结构
    private void runProgrammaticSchemaExample(SparkSession spark) {

        /**
         * people.txt
         * Michael, 29
         * Andy, 30
         * Justin, 19
         */

        // 创建一个RDD
        JavaRDD<String> peopleRDD = spark.sparkContext()
                .textFile("F:/Code/Spark/SparkSql/SparkSql/src/main/resources/people.txt", 1)
                .toJavaRDD();

        // 创建DataFrame 的结构
        // 1.定义DataFrame 的列名(字段名) 使用空格分隔
        String fieldNames = "name age";
        // 2.创建存储字段(每一列)对象的集合
        List<StructField> fields = new ArrayList<>();
        // 3.根据列名生成相应的字段对象 , 并存入 fields 集合中
        for (String fieldName : fieldNames.split(" ")) {
            StructField field = DataTypes
                    // 参数 (字段名 , 字段值类型 , 字段值是否可以为空)
                    .createStructField(fieldName, DataTypes.StringType , true);
            // 将创建的字段结构对象存入集合中
            fields.add(field);
        }

        // 创建结构类型对象 , 封装了DataFame 所有的列(字段/属性) 的对象
        // 这个对象就代表了 DataFrame的结构
        // createStructType(集合 / 数组) 要求必须是 StructField
        StructType schema = DataTypes.createStructType(fields);

        // 将原本RDD中的数据 封装到 ROW 中
        // 原本的数据 : Michael, 29
        // 封装后的数据 : ROW(Michael , 29)

        JavaRDD<Row> rowRDD = peopleRDD.map((Function<String, Row>) lines -> {

            // 对数据进行分割
            String[] attributes = lines.split(",");
            return RowFactory.create(attributes[0], attributes[1].trim());
        });

        // 将RDD 转化为 自定义结构的DataFrame
        Dataset<Row> peopleDataFrame = spark.createDataFrame(rowRDD, schema);

        /* 查询数据 */

        // 1.创建临时表
        peopleDataFrame.createOrReplaceTempView("people");

        // 2. 执行Sql 语句进行查询
        Dataset<Row> result = spark.sql("SELECT name FROM people");

        // 3.显示查询结果
        result.show();

        // 将 name 列的数据转化为 Dataset类型的
        // Map的参数 (RDD , 编码器对象)
        Dataset<String> nameDS = result.map(
                // getString(int colIndex)
                (MapFunction<Row, String>) row -> "name:" + row.getString(0),
                Encoders.STRING()
        );

        // 显示数据
        nameDS.show();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

兀坐晴窗独饮茶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值