日: 2018年11月20日

  • PythonでCloud Strageへファイルをupload

    PythonでCloud Strageへファイルをupload

    はじめに

    ローカルのファイルをCloud Strageへファイルをアップロードしたい。今回はpythonを利用することにする

    手順

    インストールから利用開始まで

    実は公式ドキュメント(https://cloud.google.com/python/)が簡潔にまとまってるw

    pip install google-cloud-storage

    して

        import os
    
        import google.cloud.storage
    
        # Create a storage client.
        storage_client = google.cloud.storage.Client()
    
        # TODO (Developer): Replace this with your Cloud Storage bucket name.
        bucket_name = 'Name of a bucket, for example my-bucket'
        bucket = storage_client.get_bucket(bucket_name)
    
        # TODO (Developer): Replace this with the name of the local file to upload.
        source_file_name = 'Local file to upload, for example ./file.txt'
        blob = bucket.blob(os.path.basename(source_file_name))
    
        # Upload the local file to Cloud Storage.
        blob.upload_from_filename(source_file_name)
    
        print('File {} uploaded to {}.'.format(
            source_file_name,
            bucket))
                    

    を作り、該当箇所を適宜変更するだけでファイルのアップロードが可能。

     

  • BigQueryにbqコマンドでテーブル作成・スキーマ変更する

    BigQueryにbqコマンドでテーブル作成・スキーマ変更する

    はじめに

    BigQueryにbqコマンドでテーブル作成・データ投入・スキーマ変更する。 ネストされたデータも扱いたいので、今回はjsonファイルを読み込むようにする CSVは現段階でネストされたデータのimportをサポートされていない

    CSV ファイルはネストされたデータや繰り返しデータに対応していません。

    https://cloud.google.com/bigquery/docs/loading-data-cloud-storage-csv ちょうどいいサンプルデータ( https://gist.github.com/isdyy/5072792 )を置いてくださる方がいたので、それを拝借。

    準備

    https://gist.github.com/isdyy/5072792 にあるように2つのデータを用意する。1つはスキーマ。もう1つはデータ

    • スキーマ
      [
        {
          "name": "kind",
          "type": "string"
        },
        {
          "name": "fullName",
          "type": "string"
        },
        {
          "name": "age",
          "type": "integer"
        },
        {
          "name": "gender",
          "type": "string"
        },
        {
          "name": "citiesLived",
          "type": "record",
          "mode": "repeated",
          "fields": [
            {
              "name": "place",
              "type": "string"
            },
            {
              "name": "numberOfYears",
              "type": "integer"
            }
          ]
        },
        {
          "name": "note",
          "type": "string"
        }
      ]

       

    • データ
    {"gender": "Male", "fullName": "John Doe", "age": 22, "citiesLived": [{"numberOfYears": 5, "place": "Seattle"}, {"numberOfYears": 6, "place": "Stockholm"}], "kind": "person"}
    {"gender": "Female", "fullName": "Jane Austen", "age": 24, "citiesLived": [{"numberOfYears": 2, "place": "Los Angeles"}, {"numberOfYears": 2, "place": "Tokyo"}], "kind": "person"}
    {"note": "with newline (\\n)", "kind": "person", "gender": "Male", "age": 30, "fullName": "newline", "citiesLived": [{"place": "Shinjuku-ku,\nTokyo"}]}
    {"note": "with tab (\\t)", "age": 30, "fullName": "tab", "citiesLived": [{"place": "Shinjuku-ku,\tTokyo"}], "kind": "person"}
    {"note": "japanese / unicode escape sequence", "gender": "Female", "citiesLived": [{"place": "\u6a2a\u6d5c\u5e02"}], "fullName": "\u6a2a\u6d5c \u82b1\u5b50 (1)", "kind": "person"}
    {"note": "japanese / raw utf-8", "gender": "Female", "citiesLived": [{"place": "横浜市"}], "fullName": "横浜 花子 (2)", "kind": "person"}
    {"note": "double-quoted string", "fullName": "\"quoted\"", "kind": "person"}

    テーブルのみ作成

    # bq mk --table logs.sample nested01.fields.json
    Table '****:logs.sample' successfully created.

    ブラウザ上で以下の通り作成されている また、bq showコマンドでスキーマを確認できる

    # bq show logs.sample 
    Table ****:logs.sample
    
       Last modified                 Schema                 Total Rows   Total Bytes   Expiration   Time Partitioning   Labels  
     ----------------- ----------------------------------- ------------ ------------- ------------ ------------------- -------- 
      19 Nov 21:09:54   |- kind: string                     0            0                                                      
                        |- fullName: string                                                                                     
                        |- age: integer                                                                                         
                        |- gender: string                                                                                       
                        +- citiesLived: record (repeated)                                                                       
                        |  |- place: string                                                                                     
                        |  |- numberOfYears: integer                                                                            
                        |- note: string  

    データの投入

    # bq load --source_format=NEWLINE_DELIMITED_JSON logs.sample nested01.data.json  
    Upload complete.
    Waiting on bqjob_r4b711f3cb6f6854b_000001672be52e12_1 ... (0s) Current status: DONE  

    無事投入された。適切にネストもされている。

    テーブル作成+データ投入

    スキーマ作成と同時に、データの投入も可能

    # bq load --source_format=NEWLINE_DELIMITED_JSON logs.sample nested01.data.json nested01.fields.json
    Upload complete.
    Waiting on bqjob_r49704f78c779ebd5_000001672bd96baa_1 ... (0s) Current status: DONE  

    もちろん結果は同じ

    データのみをつかって、テーブルを自動作成

    “` –autodetect “` オプションを使う。

    # bq load --source_format=NEWLINE_DELIMITED_JSON --autodetect  logs.sample nested01.data.json
    Upload complete.
    Waiting on bqjob_r49704f78c779ebd115_00001672bd96baa_1 ... (0s) Current status: DONE  

    スキーマを変更する

    nested01.fields.jsonを以下の通り変更

    [
      {
        "name": "kind",
        "type": "string"
      },
      {
        "name": "fullName",
        "type": "string"
      },
      {
        "name": "age",
        "type": "integer"
      },
      {
        "name": "gender",
        "type": "string"
      },
      {
        "name": "country",
        "type": "string"
      },
      {
        "name": "company",
        "type": "string"
      },
      {
        "name": "citiesLived",
        "type": "record",
        "mode": "repeated",
        "fields": [
          {
            "name": "place",
            "type": "string"
          },
          {
            "name": "numberOfYears",
            "type": "integer"
          }
        ]
      },
      {
        "name": "note",
        "type": "string"
      }
    ]
    # bq update logs.sample nested01.fields.json
    Table '****:logs.sample' successfully updated.

    スキーマが追加。 今まで投入されていたデータに追加されたカラムはnullが入る。

    新しいスキーマに、旧データを投入

    (スキーマは変更したが、投入するデータは以前と同じ)

    # bq load --source_format=NEWLINE_DELIMITED_JSON logs.sample nested01.data.json 
    Upload complete.
    Waiting on bqjob_r73583e1d3c68485e_000001672bece222_1 ... (0s) Current status: DONE   

    エラーにはならず、単純に新しいスキーマにはnullが入る

    新スキーマに沿ったデータを投入

    {"gender": "Male", "fullName": "John Doe", "age": 22, "citiesLived": [{"numberOfYears": 5, "place": "Seattle"}, {"numberOfYears": 6, "place": "Stockholm"}], "kind": "person", "country": "Japan", "company": "A company"}
    {"gender": "Female", "fullName": "Jane Austen", "age": 24, "citiesLived": [{"numberOfYears": 2, "place": "Los Angeles"}, {"numberOfYears": 2, "place": "Tokyo"}], "kind": "person", "country": "USA", "company": "B company"}
    {"note": "with newline (\\n)", "kind": "person", "gender": "Male", "age": 30, "fullName": "newline", "citiesLived": [{"place": "Shinjuku-ku,\nTokyo"}], "country": "Japan", "company": "A company"}
    {"note": "with tab (\\t)", "age": 30, "fullName": "tab", "citiesLived": [{"place": "Shinjuku-ku,\tTokyo"}], "kind": "person", "country": "USA", "company": "B company"}
    {"note": "japanese / unicode escape sequence", "gender": "Female", "citiesLived": [{"place": "\u6a2a\u6d5c\u5e02"}], "fullName": "\u6a2a\u6d5c \u82b1\u5b50 (1)", "kind": "person", "country": "Japan", "company": "A company"}
    {"note": "double-quoted string", "fullName": "\"quoted\"", "kind": "person"}
    # bq load --source_format=NEWLINE_DELIMITED_JSON logs.sample nested01.data.json 
    Upload complete.
    Waiting on bqjob_r34be71bb151950ee_000001672bf33c1d_1 ... (0s) Current status: DONE 

    投入された

    テーブル作成

    jsonファイルを作成する

    [
          {
            "name": "register_day", 
            "type": "STRING"
          }, 
          {
            "name": "rtime", 
            "type": "STRING"
          }, 
          {
            "name": "tid", 
            "type": "INTEGER"
          }, 
          {
            "name": "sid", 
            "type": "INTEGER"
          }, 
          {
            "name": "flag", 
            "type": "INTEGER"
          }, 
          {
            "name": "id", 
            "type": "INTEGER"
          }, 
          {
            "name": "lesson_date", 
            "type": "TIMESTAMP"
          }
    ]

    jsonファイルを用意して、bqコマンドで作成する

    bq mk --table --expiration 3600 --description "This is my table" --label organization:development logs.mytable testTable.json
    

    Table ‘***:logs.mytable’ successfully created. と表示されたら成功。 ブラウザで確認すると、問題なく作成されている。

    スキーマ変更

     

    [
          {
            "name": "register_day", 
            "type": "STRING"
          }, 
          {
            "name": "rtime", 
            "type": "STRING"
          }, 
          {
            "name": "tid", 
            "type": "INTEGER"
          }, 
          {
            "name": "sid", 
            "type": "INTEGER"
          }, 
          {
            "name": "flag", 
            "type": "INTEGER"
          }, 
          {
            "name": "id", 
            "type": "INTEGER"
          }, 
          {
            "name": "lesson_date", 
            "type": "TIMESTAMP"
          },
          {
            "name": "lesson_date2", 
            "type": "TIMESTAMP"
          }
    ]

    lesson_date2を追加し、bq update コマンドを実施

    bq update logs.mytable testTable.json

    Table ‘****:logs.mytable’ successfully updated.

    となれば成功 無事カラムが追加された

    テーブル定義をdumpする

    bq --format=prettyjson show --schema tsukadaproject:logs.logsPartition > bbbb
    [
      {
        "mode": "NULLABLE", 
        "name": "register_day", 
        "type": "STRING"
      }, 
      {
        "mode": "NULLABLE", 
        "name": "rtime", 
        "type": "STRING"
      }, 
      {
        "mode": "NULLABLE", 
        "name": "lesson_date", 
        "type": "TIMESTAMP"
      }
    ]

    当然このformatを読み込ませることができる

    bq mk --table --expiration 3600 --description "This is my table" --label organization:development logs.bbbb bbbb   

    パーティションテーブルを作成する

    JSONはスキーマ情報のみ。パーティションテーブルの指定はbqコマンドのオプションで行う。

    [
      {
        "mode": "NULLABLE", 
        "name": "register_day", 
        "type": "STRING"
      }, 
      {
        "mode": "NULLABLE", 
        "name": "rtime", 
        "type": "STRING"
      }, 
      {
        "mode": "NULLABLE", 
        "name": "lesson_date", 
        "type": "TIMESTAMP"
      }
    ]

    パーテョションテーブル作成

    bq mk --table --expiration 3600 --description "This is my table" --time_partitioning_field=lesson_date --time_partitioning_type=DAY --label organization:development logs.cccc cccc

    Table ‘****:logs.cccc’ successfully created.

     

    参考情報

    ストーリー仕立てで分かりやすくまとまっているのでおすすめ。