我正在使用官方的 Google Ruby gem,虽然到目前为止我尝试过的所有其他东西都运行良好(包括列出项目、数据集和表以及创建表),但启动加载作业失败,JSON 中出现以下内容错误响应:
"Job configuration must contain exactly one job-specific configuration object (e.g., query, load, extract, spreadsheetExtract), but there were 0: "
我创建的正文字符串如下所示:
--xxx
Content-Type: application/json; charset=UTF-8
{"configuration":{"load":{"destinationTable":{"projectId":"mycompany.com:projectId","datasetId":"all_events","tableId":"install"},"createDisposition":"CREATE_NEVER","writeDisposition":"WRITE_APPEND"}}}
--xxx
Content-Type: application/octet-stream
test,second,1234,6789,83838
--xxx
我之前已经install
为该数据创建了具有适当架构的表,所以这不应该是问题。
最后,为了完整起见,这里是我用来触发请求的实际代码(这是更大类中的两种方法):
def create_insert_job
config = {
'configuration' => {
'load' => {
'destinationTable' => {
'projectId' => 'mycompany.com:projectId',
'datasetId' => 'all_events',
'tableId' => 'install'
},
'createDisposition' => 'CREATE_NEVER',
'writeDisposition' => 'WRITE_APPEND'
}
}
}
body = "#{multipart_boundary}\n"
body += "Content-Type: application/json; charset=UTF-8\n"
body += "#{config.to_json}\n"
body += "#{multipart_boundary}\n"
body +="Content-Type: application/octet-stream\n"
body += "test,second,1234,6789,83838\n"
body += "#{multipart_boundary}\n"
prepare_big_query # This simply gets tokens and instantiates google_client and big_query_api
param_hash = { api_method: big_query_api.jobs.insert }
param_hash[:parameters] = {'projectId' =>'mycompany.com:projectId'}
param_hash[:body] = body
param_hash[:headers] = {'Content-Type' => "multipart/related; boundary=#{multipart_boundary}"}
result = google_client.execute(param_hash)
JSON.parse(result.response.body)
end
def multipart_boundary
'--xxx'
end
有任何想法吗?
对以下答案的补充以使此代码有效
请注意,上面的#multipart_boundary 方法返回时已经添加了“--”。这是一个问题,因为设置边界标头(在参数散列中)会在我们真正想要“xxx”时导致“--xxx”。
此外,这个 gem 的文档非常粗糙,因为在修复了我的换行问题(根据 @jcondit 的回答)后,我收到了一个关于上传到错误 URL 的新错误。那是因为您需要添加:
'uploadType' => 'multipart'
到参数,以便将请求发送到正确的 URL。
所以最终的 param_hash (同样,在修复换行符和边界问题之后)看起来像:
param_hash = { api_method: big_query_api.jobs.insert }
param_hash[:parameters] = {'projectId' => project_id, 'uploadType' => 'multipart'}
param_hash[:body] = body
param_hash[:headers] = {'Content-Type' => "multipart/related; boundary=#{multipart_boundary}"}