1

分析エンジンとしてBigqueryを使用するJavaアプリケーションに取り組んでいます。クエリジョブの挿入のコードを使用してクエリジョブを実行(および結果を取得)できました。stackoverflowに関するこのコメントを使用して、サービスアカウントを使用するようにコードを変更する必要がありました。

次に、抽出ジョブを実行して、テーブルをGoogleStorageのバケットにエクスポートする必要があります。テーブルのエクスポートに基づいて、抽出ジョブを挿入するようにJavaコードを変更できました(以下のコード)。実行すると、抽出ジョブのステータスがPENDINGからRUNNING、DONEに変わります。問題は、指定されたバケットに実際にファイルがアップロードされないことです。

役立つかもしれない情報:

  • このcreateAuthorizedClient関数はBigqueryインスタンスを返し、クエリジョブで機能するため、サービスアカウント、秘密鍵などに問題はない可能性があります。
  • また、 Googleのapi-explorerで挿入ジョブを手動で作成して実行しようとすると、ファイルがバケットに正常に作成されます。プロジェクト、データセット、テーブル、および宛先URIにコードと同じ値を使用するため、これらは正しいはずです。

コードは次のとおりです(他の誰かがこれが役立つと思った場合に備えて、ファイル全体を貼り付けます)。

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)なので、1分程度で大丈夫そうです。バケットにファイルが作成されない理由や、これをデバッグする方法がわかりません。どんな助けでもいただければ幸いです。

Craigが指摘したように、status.errorResult()とstatus.errors()の値を出力しました。

  • getErrorResults():{"メッセージ": "バックエンドエラー。ジョブが中止されました。"、 "reason": "internalError"}
  • getErrors():null
4

4 に答える 4

0

問題は、使用しているバケット名にあると思います。mybucket上記は単なる例です。これを、GoogleStorageで実際に所有しているバケットに置き換える必要があります。これまでGSを使用したことがない場合は、イントロドキュメントが役立ちます。

2番目の質問は、これをデバッグする方法でした。Jobステータスがに設定されたら、返されたオブジェクトを確認することをお勧めしDONEます。エラーで終了するジョブは、それでもDONE状態になります。違いは、エラー結果が添付されているため、job.getStatus().hasErrorResult()trueである必要があります。(私はJavaクライアントライブラリを使用したことがないので、そのメソッド名を推測しています。)詳細については、ジョブのドキュメントを参照してください。

于 2012-07-30T06:51:47.363 に答える
0

パスへの書き込み中にアクセス拒否エラーが発生したようです:gs://pixalate_test/from_java.csv。エクスポートジョブを実行していたユーザーがバケットへの書き込みアクセス権を持っていること(およびファイルがまだ存在していないこと)を確認できますか?この問題について内部bigqueryバグを報告しました...この状況ではより良いエラーを出す必要があります。。

于 2012-07-30T19:38:16.100 に答える
0

もう1つの違いは、ジョブタイプをconfig.setJobType(JOB_TYPE);として渡していないことに気付きました。ここで、constantはprivate static final String JOB_TYPE = "extract"; jsonの場合も、フォーマットを設定する必要があります。

于 2019-02-11T19:21:52.683 に答える
0

私も同じ問題を抱えていました。しかし、テーブルの名前を間違って入力したことが判明しました。ただし、Googleは「テーブルが存在しません」というエラーメッセージを生成しませんでした。それは私が私の問題を見つけるのを助けたでしょう。

ありがとう!

于 2019-07-03T22:00:12.167 に答える