我正在开发一个使用Bigquery作为分析引擎的Java应用程序。能够使用Insert a Query Job上的代码运行查询作业(并获得结果)。必须在stackoverflow上使用this comment修改代码以使用服务帐户。
现在,需要运行提取作业以将表导出到GoogleStorage上的存储桶。基于Exporting a Table,能够修改Java代码以插入提取作业(下面的代码)。运行时,提取作业的状态从PENDING更改为RUNNING更改为DONE。问题是没有文件实际上传到指定的存储桶。
可能有用的信息:
createAuthorizedClient
函数返回Bigquery实例并适用于查询作业,因此服务帐户,私钥等可能没有问题。以下是代码(粘贴完整文件以防其他人认为有用):
import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.bigquery.Bigquery;
import com.google.api.services.bigquery.Bigquery.Jobs.Insert;
import com.google.api.services.bigquery.BigqueryScopes;
import com.google.api.services.bigquery.model.Job;
import com.google.api.services.bigquery.model.JobConfiguration;
import com.google.api.services.bigquery.model.JobConfigurationExtract;
import com.google.api.services.bigquery.model.JobReference;
import com.google.api.services.bigquery.model.TableReference;
public class BigQueryJavaGettingStarted {
private static final String PROJECT_ID = "123456789012";
private static final String DATASET_ID = "MY_DATASET_NAME";
private static final String TABLE_TO_EXPORT = "MY_TABLE_NAME";
private static final String SERVICE_ACCOUNT_ID = "123456789012-...@developer.gserviceaccount.com";
private static final File PRIVATE_KEY_FILE = new File("/path/to/privatekey.p12");
private static final String DESTINATION_URI = "gs://mybucket/file.csv";
private static final List<String> SCOPES = Arrays.asList(BigqueryScopes.BIGQUERY);
private static final HttpTransport TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
public static void main (String[] args) {
try {
executeExtractJob();
} catch (Exception e) {
e.printStackTrace();
}
}
public static final void executeExtractJob() throws IOException, InterruptedException, GeneralSecurityException {
Bigquery bigquery = createAuthorizedClient();
//Create a new Extract job
Job job = new Job();
JobConfiguration config = new JobConfiguration();
JobConfigurationExtract extractConfig = new JobConfigurationExtract();
TableReference sourceTable = new TableReference();
sourceTable.setProjectId(PROJECT_ID).setDatasetId(DATASET_ID).setTableId(TABLE_TO_EXPORT);
extractConfig.setSourceTable(sourceTable);
extractConfig.setDestinationUri(DESTINATION_URI);
config.setExtract(extractConfig);
job.setConfiguration(config);
//Insert/Execute the created extract job
Insert insert = bigquery.jobs().insert(PROJECT_ID, job);
insert.setProjectId(PROJECT_ID);
JobReference jobId = insert.execute().getJobReference();
//Now check to see if the job has successfuly completed (Optional for extract jobs?)
long startTime = System.currentTimeMillis();
long elapsedTime;
while (true) {
Job pollJob = bigquery.jobs().get(PROJECT_ID, jobId.getJobId()).execute();
elapsedTime = System.currentTimeMillis() - startTime;
System.out.format("Job status (%dms) %s: %s\n", elapsedTime, jobId.getJobId(), pollJob.getStatus().getState());
if (pollJob.getStatus().getState().equals("DONE")) {
break;
}
//Wait a second before rechecking job status
Thread.sleep(1000);
}
}
private static Bigquery createAuthorizedClient() throws GeneralSecurityException, IOException {
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountScopes(SCOPES)
.setServiceAccountId(SERVICE_ACCOUNT_ID)
.setServiceAccountPrivateKeyFromP12File(PRIVATE_KEY_FILE)
.build();
return Bigquery.builder(TRANSPORT, JSON_FACTORY)
.setApplicationName("My Reports")
.setHttpRequestInitializer(credential)
.build();
}
}
这是输出:
Job status (337ms) job_dc08f7327e3d48cc9b5ba708efe5b6b5: PENDING
...
Job status (9186ms) job_dc08f7327e3d48cc9b5ba708efe5b6b5: PENDING
Job status (10798ms) job_dc08f7327e3d48cc9b5ba708efe5b6b5: RUNNING
...
Job status (53952ms) job_dc08f7327e3d48cc9b5ba708efe5b6b5: RUNNING
Job status (55531ms) job_dc08f7327e3d48cc9b5ba708efe5b6b5: DONE
这是一张小桌子(大约4MB)所以大约一分钟的工作似乎没问题。不知道为什么在桶中没有创建文件或者如何调试它。任何帮助将不胜感激。
正如Craig指出的那样,打印了status.errorResult()和status.errors()值。
答案 0 :(得分:0)
我认为问题在于您使用的存储桶名称 - 上面的mybucket
只是一个示例,您需要将其替换为您在Google存储中实际拥有的存储桶。如果您以前从未使用过GS,那么intro docs会有所帮助。
你的第二个问题是如何调试它 - 我建议在状态设置为Job
后查看返回的DONE
对象。以错误结束的作业仍会使其处于DONE
状态,不同之处在于它们附加了错误结果,因此job.getStatus().hasErrorResult()
应该为真。 (我从未使用过Java客户端库,因此我猜测该方法名称。)您可以在jobs docs中找到更多信息。
答案 1 :(得分:0)
看起来写入路径时出现拒绝访问错误:gs://pixalate_test/from_java.csv。您是否可以确保执行导出作业的用户具有对存储桶的写入权限(并且该文件尚不存在)? 我已经在这个问题上提交了一个内部bigquery错误...我们应该在这种情况下给出一个更好的错误。
答案 2 :(得分:0)
另一个区别是,我注意到您没有将作业类型作为config.setJobType(JOB_TYPE)传递; 其中常量是私有静态最终字符串JOB_TYPE =“ extract”; 同样对于json,也需要设置格式。
答案 3 :(得分:0)
我有同样的问题。但事实证明,我输入了错误的表名。但是,Google并未生成错误消息,指出“该表不存在”。那会帮助我找到问题所在。
谢谢!