表題の件で躓いてしまったので、ここで書いておく。
"Job configuration must contain exactly one job-specific configuration object (e.g., query, load, extract, spreadsheetExtract), but there were 0: " というエラーが出て、うまくロードできない、という現象。
結論からいうと、ここのStackOverflowでのやりとりが手がかりとなって、下記のようなコードでなんとかロードすることができた。リファクタもなにもしてないコードで、失礼。(gist)
require 'bundler/setup'
require 'google/api_client'
require 'yaml'
require 'json'
def multipart_boundary
'xxx'
end
oauth_yaml = YAML.load_file('.google-api.yaml')
client = Google::APIClient.new(
:application_name => 'Example Ruby Bigquery',
:application_version => '1.0.0')
client.authorization.client_id = oauth_yaml["client_id"]
client.authorization.client_secret = oauth_yaml["client_secret"]
client.authorization.scope = oauth_yaml["scope"]
client.authorization.refresh_token = oauth_yaml["refresh_token"]
client.authorization.access_token = oauth_yaml["access_token"]
bq_client = client.discovered_api('bigquery', 'v2')
job_config = {
'configuration' => {
'load' => {
'sourceUris' => ['gs://a-know-test/sample.csv'],
'schema' => {
'fields' => [
{
'name' => 'id',
'type' => 'INTEGER'
},
{
'name' => 'name',
'type' => 'STRING'
},
{
'name' => 'price',
'type' => 'INTEGER'
},
]
},
'destinationTable' => {
'projectId' => 'test-001',
'datasetId' => 'test',
'tableId' => 'sample'
},
'createDisposition' => 'CREATE_NEVER',
'writeDisposition' => 'WRITE_APPEND'
}
}
}
body = "--#{multipart_boundary}\n"
body += "Content-Type: application/json; charset=UTF-8\n"
body += "\n"
body += "#{job_config.to_json}\n"
body += "--#{multipart_boundary}--\n"
result = client.execute(
:api_method => bq_client.jobs.insert,
:parameters => {
'projectId' => '234230709110',
'uploadType' => 'multipart'
},
:body => body,
:headers => { 'Content-Type' => "multipart/related; boundary=#{multipart_boundary}" }
)
puts result.data
puts result.response.body
自分的につまづきポイントだと思った点を、いくつか挙げてみる。
- "Job configuration must contain〜" のエラーは、リクエストのパラメータになんらかの不備があった場合に出る
- 特定のパラメータに不備があるときだけに出るようなものではないので厄介
- body には configuration のjsonだけじゃだめ
- Content-Type の指定とか multipart boundary とかもいる
- しかも Content-Type の指定の次に空行が必要
- headers には以下の2点の指定が必要
- Content-Type として multipart/related
- ハイフンのプレフィックスを省いた multipart boundary
- body末尾の boundary にはサフィックスとしてハイフンが必要
- parameters に 'uploadType' => 'multipart' の指定が必要(これはここにも書いてある)
この body の書き方って、こういうお作法でしたっけ。今までにも APIリクエストの際のリクエストbody をいじってたことはあったけど、こんな書き方、したっけなぁ。
「Ruby で BigQuery」は、ちょっとわけあって今後も少しづつ試していこうと思っているので、同じような境遇の方はこちらを watch して頂ければと。