Spark BigQuery 连接器:写入 ARRAY 类型会导致异常:“”无效值:ARRAY 不是有效值“”

Posted

技术标签:

【中文标题】Spark BigQuery 连接器:写入 ARRAY 类型会导致异常:“”无效值:ARRAY 不是有效值“”【英文标题】:Spark BigQuery Connector: Writing ARRAY type causes exception: ""Invalid value for: ARRAY is not a valid value"" 【发布时间】:2017-06-06 23:28:49 【问题描述】:

在 Google Cloud Dataproc 中运行 Spark 作业。使用 BigQuery Connector 将作业输出的 json 数据加载到 BigQuery 表中。

BigQuery Standard-SQL data types documentation 声明支持 ARRAY 类型。

我的 Scala 代码是:

val outputDatasetId = "mydataset"
val tableSchema = "["+
    "'name': '_id', 'type': 'STRING',"+
    "'name': 'array1', 'type': 'ARRAY',"+
    "'name': 'array2', 'type': 'ARRAY',"+
    "'name': 'number1', 'type': 'FLOAT'"+
    "]"

// Output configuration
BigQueryConfiguration.configureBigQueryOutput(
    conf, projectId, outputDatasetId, "outputTable", 
    tableSchema)

//Write visits to BigQuery
jsonData.saveAsNewAPIHadoopDataset(conf)

但是作业抛出了这个异常:


  "code" : 400,
  "errors" : [ 
  "domain" : "global",
  "message" : "Invalid value for: ARRAY is not a valid value",
  "reason" : "invalid"
    ],
  "message" : "Invalid value for: ARRAY is not a valid value"

    at 

com.google.cloud.hadoop.util.AbstractGoogleAsyncWriteChannel.waitForCompletionAnThrowIfUploadFailed(AbstractGoogleAsyncWriteChannel.java:432)
    at com.google.cloud.hadoop.util.AbstractGoogleAsyncWriteChannel.close(AbstractGoogleAsyncWriteChannel.java:287)
    at com.google.cloud.hadoop.io.bigquery.BigQueryRecordWriter.close(BigQueryRecordWriter.java:358)
    at org.apache.spark.rdd.PairRDDFunctions$$anonfun$saveAsNewAPIHadoopDataset$1$$anonfun$12$$anonfun$apply$5.apply$mcV$sp(PairRDDFunctions.scala:1124)
    at org.apache.spark.util.Utils$.tryWithSafeFinallyAndFailureCallbacks(Utils.scala:1366)
    ... 8 more
Caused by: com.google.api.client.googleapis.json.GoogleJsonResponseException: 
400 Bad Request

这是传统 SQL 与标准 SQL 的问题吗?还是 BigQuery Connector for Spark 不支持 ARRAY 类型?

【问题讨论】:

如何使用 spark bigquery 连接器处理空值。除了使用 dataframe.na 函数之外,还有其他选择吗?谢谢 【参考方案1】:

不要使用type=ARRAY,而是像往常一样尝试设置type,但也要设置密钥mode=REPEATED

例如,一个字符串数组将被定义为:

'name': 'field1', 'type': 'STRING', 'mode': 'REPEATED'

【讨论】:

完美。解决了。感谢您复制/粘贴代码块。 如何使用 spark bigquery 连接器处理空值。除了使用 dataframe.na 函数之外,还有其他选择吗?谢谢 @Phoenix 嗯,我不确定。我建议在 SO 上问这个问题,你可能会在这个问题上得到更好的答案。 可以通过将模式提及为'NULLABLE'来处理。现在我实际上需要为模式指定 NULLABLE 和 REPEATED。我传递的方式与 "mode": ["REPEATED","NULLABLE"] 相同,这似乎不是正确的方式。【参考方案2】:

这些是字符串数组吗?整数?我相信使用此 API,您需要将 type 设置为元素类型,例如STRINGINT64,但使用 modeREPEATED。 BigQuery API 尚未完全更新为在任何地方使用标准 SQL 类型,因此您需要改用传统的 type + 模式约定。

【讨论】:

@***.com/users/6253347/elliott-brossard 。在传递模式以使用 json 字符串创建表时,我们如何在模式键中同时包含“NULLABLE”和“REPEATED”。谢谢 没有这个选项。

以上是关于Spark BigQuery 连接器:写入 ARRAY 类型会导致异常:“”无效值:ARRAY 不是有效值“”的主要内容,如果未能解决你的问题,请参考以下文章

加载到 BigQuery 时,Spark 写入 Parquet array<string> 会转换为不同的数据类型

Spark on YARN 和 spark-bigquery 连接器

使用 Spark BigQuery 连接器启动 Dataproc 集群

如何通过 Spark SQL 连接 BigQuery?

Google BigQuery Spark 连接器:如何在追加时忽略未知值

使用 scala 从 spark 中删除 bigquery 表