Загрузка файла CSV в BigQuery с одним столбцом, содержащим все пустые значения - PullRequest
0 голосов
/ 20 декабря 2018

Я хочу добавить следующий файл , используя Python API, в таблицу BigQuery с нижеуказанной схемой:

[
   {
    "name": "batsman",
    "type": "STRING",
    "mode": "NULLABLE"
   },
   {
    "name": "batting_team",
    "type": "STRING",
    "mode": "NULLABLE"
   },
   {
    "name": "bowler",
    "type": "STRING",
    "mode": "NULLABLE"
   },
   {
    "name": "city",
    "type": "STRING",
    "mode": "NULLABLE"
   },
   {
    "name": "date",
    "type": "DATE",
    "mode": "NULLABLE"
   },
   {
    "name": "delivery",
    "type": "FLOAT",
    "mode": "NULLABLE"
   },
   {
    "name": "extras",
    "type": "INTEGER",
    "mode": "NULLABLE"
   },
   {
    "name": "extras_type",
    "type": "STRING",
    "mode": "NULLABLE"
   },
   {
    "name": "inning",
    "type": "INTEGER",
    "mode": "NULLABLE"
   },
   {
    "name": "match_code",
    "type": "INTEGER",
    "mode": "NULLABLE"
   },
   {
    "name": "non_striker",
    "type": "STRING",
    "mode": "NULLABLE"
   },
   {
    "name": "player_out",
    "type": "STRING",
    "mode": "NULLABLE"
   },
   {
    "name": "runs",
    "type": "INTEGER",
    "mode": "NULLABLE"
   },
   {
    "name": "team1",
    "type": "STRING",
    "mode": "NULLABLE"
   },
   {
    "name": "team2",
    "type": "STRING",
    "mode": "NULLABLE"
   },
   {
    "name": "toss_decision",
    "type": "STRING",
    "mode": "NULLABLE"
   },
   {
    "name": "toss_winner",
    "type": "STRING",
    "mode": "NULLABLE"
   },
   {
    "name": "total",
    "type": "INTEGER",
    "mode": "NULLABLE"
   },
   {
    "name": "venue",
    "type": "STRING",
    "mode": "NULLABLE"
   },
   {
    "name": "wicket_fielders",
    "type": "STRING",
    "mode": "NULLABLE"
   },
   {
    "name": "wicket_kind",
    "type": "STRING",
    "mode": "NULLABLE"
   },
   {
    "name": "win_margin",
    "type": "INTEGER",
    "mode": "NULLABLE"
   },
   {
    "name": "win_type",
    "type": "STRING",
    "mode": "NULLABLE"
   },
   {
    "name": "winner",
    "type": "STRING",
    "mode": "NULLABLE"
   }
  ]

Код, который я использую для добавления вBigQuery выглядит следующим образом:

def insert_data_in_bq(bucketname, csv_filepath, table_id='ipl'):
    """Appends a csv to a BigQuery table."""
    client = bigquery.Client()
    dataset_id = 'cric'
    dataset_ref = client.dataset(dataset_id)
    job_config = bigquery.LoadJobConfig()
    job_config.autodetect = True
    job_config.skip_leading_rows = 1
    job_config.source_format = bigquery.SourceFormat.CSV
    # job_config.null_marker = 'NULL'
    uri = 'gs://' + bucketname + '/' + csv_filepath
    load_job = client.load_table_from_uri(uri, dataset_ref.table(table_id), 
    job_config=job_config)  # API request
    print('Starting job {}'.format(load_job.job_id))
    load_job.result()  # Waits for table load to complete.
    print('Job finished.')
    print('Loaded {} rows.'.format(load_job.output_rows))

Однако всякий раз, когда я загружаю файл, я получаю сообщение об ошибке:

BadRequest: 400 Invalid schema update. Field win_margin has changed type from INTEGER to STRING

Обычный файл будет выглядеть как this .

Что я должен сделать, чтобы я мог сохранить столбец win_margin как INTEGER и все же иметь возможность загрузить этот файл, содержащий все пустые строки для столбца?

Ответы [ 2 ]

0 голосов
/ 24 декабря 2018

Необходимо указать схему таблицы, в которой тип столбца win_margin указан явно.Вы можете сделать это, установив job_config.schema поле и установив job_config.autodetect в False.

Ниже приведена функция, которую вы можете использовать для чтения схемы из файла:

def read_bigquery_schema_from_file(filepath):
    file_content = open(filepath).read()
    json_content = json.loads(file_content)
    return read_bigquery_schema_from_json_recursive(json_content)

def read_bigquery_schema_from_json_recursive(json_schema):
    """
    CAUTION: Recursive function
    This method can generate BQ schemas for nested records
    """
    result = []
    for field in json_schema:
        if field.get('type').lower() == 'record' and field.get('fields'):
            schema = SchemaField(
                name=field.get('name'),
                field_type=field.get('type', 'STRING'),
                mode=field.get('mode', 'NULLABLE'),
                description=field.get('description'),
                fields=read_bigquery_schema_from_json_recursive(field.get('fields'))
            )
        else:
            schema = SchemaField(
                name=field.get('name'),
                field_type=field.get('type', 'STRING'),
                mode=field.get('mode', 'NULLABLE'),
                description=field.get('description')
            )
        result.append(schema)
    return result
0 голосов
/ 21 декабря 2018

Как вы видите, BigQuery не позволит вам добавить пустое значение в поле Integer, поэтому вам нужно заполнить это поле либо при создании файла, либо при загрузке, например:

  1. При сборкеубедитесь, что файл win_margin не пустой, укажите 0 или ноль
  2. Если это невозможно, вам потребуется обновить код Python, чтобы обновить значение поля перед загрузкой
  3. Создать формулу вСам лист для заполнения поля
  4. Загрузите файл в другую таблицу в BQ и выполните команду SQL для перемещения данных из одной таблицы в другую
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...