将模式添加到Java中的数据集[行]

时间:2019-04-12 08:59:04

标签: apache-spark spark-structured-streaming

我是Spark的新手,正在尝试探索Spark结构化的流。我将使用来自Kafka(嵌套JSON)的消息,并根据JSON属性上的某些条件过滤这些消息。然后,满足过滤条件的每条消息都应推送到Cassandra。

我已经阅读了Spark Cassandra连接器的文档 https://spark.apache.org/docs/2.2.0/structured-streaming-kafka-integration.html

Dataset<Row> df = spark
.readStream()
.format("kafka")
.option("kafka.bootstrap.servers", "host1:port1,host2:port2")
.option("subscribe", "topic1")
.load() 

df.selectExpr("CAST(value AS STRING)")

我只需要此嵌套JSON中存在的许多属性中的几个即可。如何在其之上应用模式,以便可以使用sparkSQL进行过滤?

对于示例JSON,我需要为玩频总和大于5的玩家保留姓名,年龄,经验,hobby_name和hobby_experience。

{
    "name": "Tom",
    "age": "24",
    "gender": "male",
    "hobbies": [{
        "name": "Tennis",
        "experience": 5,
        "places": [{
            "city": "London",
            "frequency": 4
        }, {
            "city": "Sydney",
            "frequency": 3
        }]
    }]
}

我对Spark还是比较陌生,如果这是重复的话,请原谅。另外,我正在寻找JAVA中的解决方案。

1 个答案:

答案 0 :(得分:0)

您可以这样指定模式:

import org.apache.spark.sql.types.{DataTypes, StructField, StructType};

StructType schema = DataTypes.createStructType(new StructField[] {
    DataTypes.createStructField("name",  DataTypes.StringType, true),
    DataTypes.createStructField("age", DataTypes.StringType, true),
    DataTypes.createStructField("gender", DataTypes.StringType, true),
    DataTypes.createStructField("hobbies", DataTypes.createStructType(new StructField[] {
        DataTypes.createStructField("name", DataTypes.StringType, true),
        DataTypes.createStructField("experience", DataTypes.IntegerType, true),
        DataTypes.createStructField("places", DataTypes.createStructType(new StructField[] {
            DataTypes.createStructField("city", DataTypes.StringType, true),
            DataTypes.createStructField("frequency", DataTypes.IntegerType, true)
        }), true)
    }), true)
});

然后根据需要使用架构创建数据框:

import org.apache.spark.sql.functions.{col, from_json};

df.select(from_json(col("value"), schema).as("data"))
  .select(
    col("data.name").as("name"),
    col("data.hobbies.name").as("hobbies_name"))