我正在尝试使用以下命令将数据从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以及为什么上面的代码段不起作用? 有人有线索吗?
答案 0 :(得分:2)
iter
是Iterator
。因此,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}}如果您想要使用它两次而不重新计算它。)