我有一个包含列的csv文件,出于测试目的,我将其手动推送到Kafka,然后从那里将其读入Spark并应用一些解析,并且为测试目的做了控制台输出。现在我了解了csv数据在结构化流中作为Value进行流传输,并将其强制转换为String。我的要求是是否可以将值数据转换为实际列。 csv文件中有数百列,但我只查看两个特定的列“ SERVICE_NAME8”和“ _raw”
当我从路径读取csv文件时,我使用spark.sql提取这些列,但是现在我使用结构化流式传输,我不确定是否可以将这些特定的列提取为新的数据帧并在以后应用解析
val df = spark
.readStream
.format("kafka")
.option("kafka.bootstrap.servers", "10.160.172.45:9092, 10.160.172.46:9092, 10.160.172.100:9092")
.option("subscribe", "TOPIC_WITH_COMP_P2_R2, TOPIC_WITH_COMP_P2_R2.DIT, TOPIC_WITHOUT_COMP_P2_R2.DIT")
.load()
val dfs = df.selectExpr("CAST(value AS STRING)").toDF()
val data =dfs.withColumn("splitted", split($"value", "/"))
.select($"splitted".getItem(4).alias("region"),$"splitted".getItem(5).alias("service"),col("value"))
.withColumn("service_type", regexp_extract($"service", """.*(Inbound|Outbound|Outound).*""",1))
.withColumn("region_type", concat(
when(col("region").isNotNull,col("region")).otherwise(lit("null")), lit(" "),
when(col("service").isNotNull,col("service_type")).otherwise(lit("null"))))
val extractedDF = data.filter(
col("region").isNotNull &&
col("service").isNotNull &&
col("value").isNotNull &&
col("service_type").isNotNull &&
col("region_type").isNotNull)
.filter("region != ''")
.filter("service != ''")
.filter("value != ''")
.filter("service_type != ''")
.filter("region_type != ''")
val query = extractedDF
.writeStream
.format("console")
.outputMode("append")
.trigger(ProcessingTime("20 seconds"))
.start()
在val dfs = df.selectExpr(“ CAST(value AS STRING)”)。toDF()之后,我以某种方式只需要提取两列“ SERVICE_NAME8”和“ _raw”,剩下的就由解析进行并产生输出>
答案 0 :(得分:0)
在Spark structured streaming快速示例中,您可以看到
df.as[String].map(_.split("/"))
应该将流转换为与spark.sql代码相同的data
。
接下来,您可以仅提取所需的列并进行处理。例如
data.map(line=>(line[SERVICE_NAME_COLUMN_INDEX], line[RAW_COLUMN_INDEX]))
每行将获得两列的Tuple
。
请注意,这只是示例。我不运行。另外,我认为Tuple
不是最佳解决方案。