JDBCRDD或RDD中的聚合

时间:2015-10-01 03:05:10

标签: scala apache-spark aggregation rdd

我是Sacla和Spark的新手,我尝试使用jdbcRDD使用Spark在SqlServer上创建SQL查询,并使用映射和聚合对其进行一些转换。 这就是我所拥有的,一个包含n个String列和m个Number列的表。 像

"A", "A1",1,2
"A", "A1",4,3
"A", "A2",3,4
"B", "B1",6,7
...
...

我正在寻找的是创建一个分层结构,将字符串分组并聚合数字列,如

A
|->A1
   |->(5,5)
|->A2
   |->(3,4)
B
|->B1
   |->(6,7)

我能够创建hierarchie但我无法在数值列表中执行聚合。

1 个答案:

答案 0 :(得分:1)

如果您通过JDBC加载数据,我只需使用DataFrames:

import sqlContext.implicits._
import org.apache.spark.sql.functions.sum
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.DataFrame


val options: Map[(String, String)] = ???
val df: DataFrame = sqlContext.read
 .format("jdbc")
 .options(options)
 .load()
 .toDF("k1", "k2", "v1", "v2")

df.printSchema

// root
//  |-- k1: string (nullable = true)
//  |-- k2: string (nullable = true)
//  |-- v1: integer (nullable = true)
//  |-- v2: integer (nullable = true)

df.show

// +---+---+---+---+
// | k1| k2| v1| v2|
// +---+---+---+---+
// |  A| A1|  1|  2|
// |  A| A1|  4|  3|
// |  A| A2|  3|  4|
// |  B| B1|  6|  7|
// +---+---+---+---+

使用上面的输入,您只需要一个基本的聚合

df
  .groupBy($"k1", $"k2")
  .agg(sum($"v1").alias("v1"), sum($"v2").alias("v2")).show

// +---+---+---+---+                                                           
// | k1| k2| v1| v2|
// +---+---+---+---+
// |  A| A1|  5|  5|
// |  A| A2|  3|  4|
// |  B| B1|  6|  7|
// +---+---+---+---+

如果你有这样的RDD:

val rdd RDD[(String, String, Int, Int)] = ???
rdd.first
// (String, String, Int, Int) = (A,A1,1,2)

没有理由构建复杂的层次结构。简单的PairRDD应该足够了:

val aggregated: RDD[((String, String), breeze.linalg.Vector[Int])] = rdd
  .map{case (k1, k2, v1, v2) => ((k1, k2), breeze.linalg.Vector(v1, v2))}
  .reduceByKey(_ + _)

aggregated.first
// ((String, String), breeze.linalg.Vector[Int]) = ((A,A2),DenseVector(3, 4))

保持层次结构无效,但您可以将RDD组合在一起,如下所示:

aggregated.map{case ((k1, k2), v) => (k1, (k2, v))}.groupByKey