Scala joinWithCassandraTable结果(或CassandraTableScanRDD)到Dataset

时间:2017-09-27 18:13:47

标签: apache-spark cassandra rdd spark-cassandra-connector

我使用Datastax spark-cassandra-connector访问Cassandra中的某些数据。

为了能够有效地访问我查询所需的所有数据,我必须使用joinWithCassandraTable方法从一堆分区中获取数据。这给了我一个类com.datastax.spark.connector.rdd.CassandraTableScanRDD的对象(或者类似的,测试我实际上只是使用标准sc.cassandraTable(ks, tbl)方法来读取数据)。

问题是,我需要在结果对象上使用的所有方法都需要类org.apache.spark.sql.Dataset的对象。

我已经做了很多搜索,并且找不到任何可以帮助的东西 - 我发现的最近的是this类似的问题,我不认为已经得到了充分的回答,因为它忽略了使用joinWithCassandraTable来访问所有必要数据的推荐方法的用例。

我也是java和scala的新手,很抱歉,如果我有点慢。任何帮助都将受到大力赞赏,因为我现在已经陷入困境。

谢谢, AKHIL

1 个答案:

答案 0 :(得分:3)

您可以做的是将您的RDD读入RDD [Row],然后将其更改为DataFrame。我们唯一的问题是我们还需要Schema。所以我们分两步完成。

首先,让我们从连接目标

以编程方式获取架构
val schema = spark.read.cassandraFormat("dogabase", "test").load.schema

/**
schema: org.apache.spark.sql.types.StructType = 
StructType(StructField(owner,StringType,true), 
StructField(dog_id,IntegerType,true), 
StructField(dog_age,IntegerType,true), 
StructField(dog_name,StringType,true))
**/

然后我们可以从我们的Cassandra Driver中制作org.apache.spark.sql.Row个对象 行。

import org.apache.spark.sql.Row
val joinResult = 
  sc.parallelize(Seq(Tuple1("Russ")))
    .joinWithCassandraTable("test", "dogabase")
    .map{ case(_, cassandraRow) => Row(cassandraRow.columnValues:_*)} //Unpack our Cassandra row values into a spark.sql.Row

现在我们有了一个架构和一个RDD [Row],我们可以使用spark会话的createDataFrame方法

val dataset = spark.createDataFrame(joinResult, schema)
dataset.show

/**
+-----+------+-------+--------+
|owner|dog_id|dog_age|dog_name|
+-----+------+-------+--------+
| Russ|     1|     10|    cara|
| Russ|     2|     11|sundance|
+-----+------+-------+--------+
**/

只是因为你不相信我的DataFrame是数据集

dataset.getClass
Class[_ <: org.apache.spark.sql.DataFrame] = class org.apache.spark.sql.Dataset

编辑:可能需要的转换器

某些Cassandra类型不是Spark Rows的有效基础,因此您可能需要转换它们。这可以通过编写快速转换功能来完成。不幸的是,SCC使用的内置转换构成了内部表示,因此我们无法使用这些转换。

def convertToSpark(element:Any): Any = {
  case time: org.joda.time.LocalDate => time.toDateTimeAtStartOfDay().toDate //Convert to java.util.Date
  case other => other
}

然后在制作行时

cassandraRow.columnValues.map(convertToSpark):_*