将镶木地板文件存储到PostgreSQL数据库中

时间:2018-04-20 09:25:20

标签: postgresql apache-spark jdbc pyspark parquet

我想将拼凑文件写入PostgreSQL。我正在使用Spark并编写我正在使用Spark Dataframe的write.jdbc函数的文件。一切都适用于镶木柱类型,如长,小数或文本。问题在于像Map这样的复杂类型。我想在我的PostgreSQL中将Map存储为json。因为我知道PostgreSQL可以自动将文本数据类型转换为json(使用强制转换操作)所以我将地图转储到json字符串。

但是火花程序抱怨我们正在尝试将“字符变化”数据类型插入到“json”类型的列中。这表明PostgreSQL没有自动将“字符变化”转换为JSON。

我继续登录我的数据库并手动尝试将JSON字符串插入到表的JSON数据类型列中并且它有效。

我的问题是为什么我的火花程序抱怨施法操作?

我正在使用Spark版本1.6.1,PostgreSQL 4.3和JDBC 42.1.1

以下是代码段

url = "jdbc:postgresql://host_name:host_port/db_name"
data_frame.write.jdbc(url, table_name, properties={"user": user, "password": password})

错误堆栈跟踪:

Hint: You will need to rewrite or cast the expression.
  Position: 66  Call getNextException to see other errors in the batch.
    at org.postgresql.jdbc.BatchResultHandler.handleError(BatchResultHandler.java:148)
    at org.postgresql.core.ResultHandlerDelegate.handleError(ResultHandlerDelegate.java:50)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2190)
    at org.postgresql.core.v3.QueryExecutorImpl.flushIfDeadlockRisk(QueryExecutorImpl.java:1325)
    at org.postgresql.core.v3.QueryExecutorImpl.sendQuery(QueryExecutorImpl.java:1350)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:458)
    at org.postgresql.jdbc.PgStatement.executeBatch(PgStatement.java:791)
    at org.postgresql.jdbc.PgPreparedStatement.executeBatch(PgPreparedStatement.java:1547)
    at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils$.savePartition(JdbcUtils.scala:215)
    at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils$$anonfun$saveTable$1.apply(JdbcUtils.scala:277)
    at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils$$anonfun$saveTable$1.apply(JdbcUtils.scala:276)
    at org.apache.spark.rdd.RDD$$anonfun$foreachPartition$1$$anonfun$apply$33.apply(RDD.scala:920)
    at org.apache.spark.rdd.RDD$$anonfun$foreachPartition$1$$anonfun$apply$33.apply(RDD.scala:920)
    at org.apache.spark.SparkContext$$anonfun$runJob$5.apply(SparkContext.scala:1858)
    at org.apache.spark.SparkContext$$anonfun$runJob$5.apply(SparkContext.scala:1858)
    at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:66)
    at org.apache.spark.scheduler.Task.run(Task.scala:89)
    at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:214)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    ... 1 more
Caused by: org.postgresql.util.PSQLException: ERROR: column "value" is of type json but expression is of type character varying
  Hint: You will need to rewrite or cast the expression.
  Position: 66
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2476)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2189)
    ... 18 more

2 个答案:

答案 0 :(得分:3)

已经很晚了,但这是所有迷失灵魂的答案。

您需要将“ stringtype”参数传递给JDBC。它指定在绑定通过setString()设置的PreparedStatement参数时要使用的类型。默认情况下,它是varchar,它强制将参数设为varchar并阻止任何强制转换操作(在我的情况下,是JSON字符串到JSON)。如果指定,则stringtype ==“ unspecified”,然后将其留给数据库来确定参数是哪种类型。就我而言,这有助于Postgres将字符串轻松转换为JSON的方式。

文档:https://jdbc.postgresql.org/documentation/head/connect.html

答案 1 :(得分:0)

您是否正在使用AWS服务。如果是,则使用aws胶来抓取您的文件,从而创建一个表。创建一个粘合作业,将该数据(表)作为输入目录,并为输出选择aws rds jdbc连接并选择所需的数据库。运行作业,您的Paraquet文件数据将被加载到postgres表中。

相关问题