Scala mapPartition在分区上收集什么都不做

时间:2015-12-06 16:03:58

标签: scala apache-spark datastax-enterprise rdd

我正在尝试使用以下命令将数据从rdd移动到postgres表:

def copyIn(reader: java.io.Reader, columnStmt: String = "") = {
        //connect to postgres database on the localhost
        val driver = "org.postgresql.Driver"
        var connection:Connection = null
        Class.forName(driver)
        connection = DriverManager.getConnection()

        try {
            connection.unwrap(classOf[PGConnection]).getCopyAPI.copyIn(s"COPY my_table ($columnStmt) FROM STDIN WITH CSV", reader)
        } catch {
            case se: SQLException => println(se.getMessage)
            case t: Throwable => println(t.getMessage)
        } finally {
            connection.close()
        }
    }

myRdd.mapPartitions(iter => {
        val sb = new StringBuilder()

        var n_iter = iter.map(row => {
            val mapRequest = Utils.getMyRowMap(myMap, row)
            sb.append(mapRequest.values.mkString(", ")).append("\n")
        })

        copyIn(new StringReader(sb.toString), geoSelectMap.keySet.mkString(", "))
        sb.clear
        n_iter
    }).collect

脚本继续进入CopyIn函数,没有要插入的数据。我想这可能是因为iter.map只是映射分区而不执行收集?我尝试收集整个myRdd对象,但仍然没有在copyIn函数中获取数据。

如何迭代rdd并获取附加的StringBuilder以及为什么上面的代码段不起作用? 有人有线索吗?

1 个答案:

答案 0 :(得分:2)

iterIterator。因此,iter.map会创建一个新的Iterator,但您实际上并没有对其进行迭代,也没有做任何事情。您可能需要foreach。除非iter在您返回时为collect,否则foreachPartition的结果将为空RDD。

您想要的实际方法是myRdd.foreachPartition(iter => { val sb = new StringBuilder() iter.foreach(row => { val mapRequest = Utils.getMyRowMap(myMap, row) sb.append(mapRequest.values.mkString(", ")).append("\n") }) copyIn(new StringReader(sb.toString), geoSelectMap.keySet.mkString(", ")) sb.clear })

myRdd.collect

然后myRdd如果你想收集它。 (Persist {{1}}如果您想要使用它两次而不重新计算它。)