Airflow BigQueryOperator:如何在分区表中保存查询结果?

时间:2018-05-24 08:55:56

标签: google-bigquery airflow

我有一个简单的DAG

from airflow import DAG
from airflow.contrib.operators.bigquery_operator import BigQueryOperator

with DAG(dag_id='my_dags.my_dag') as dag:

    start = DummyOperator(task_id='start')

    end = DummyOperator(task_id='end')
    sql = """
             SELECT *
             FROM 'another_dataset.another_table'
          """
    bq_query = BigQueryOperator(bql=sql,
                            destination_dataset_table='my_dataset.my_table20180524'),
                            task_id='bq_query',
                            bigquery_conn_id='my_bq_connection',
                            use_legacy_sql=False,
                            write_disposition='WRITE_TRUNCATE',
                            create_disposition='CREATE_IF_NEEDED',
                            query_params={})
    start >> bq_query >> end

执行bq_query任务时,SQL查询将保存在分片表中。我希望它保存在每日分区表中。为此,我只将destination_dataset_table更改为my_dataset.my_table$20180524。执行bq_task时,我收到了以下错误:

Partitioning specification must be provided in order to create partitioned table

如何指定BigQuery将查询结果保存到每日分区表?我的第一个猜测是在query_params中使用BigQueryOperator 但我没有找到关于如何使用该参数的任何示例。

修改

我使用google-cloud==0.27.0 python客户端......它是Prod中使用的那个:(

4 个答案:

答案 0 :(得分:3)

首先需要创建一个空的分区目标表。按照此处的说明操作:link创建一个空的分区表

然后再次在气流管道下方运行。 你可以试试代码:

import datetime
from airflow import DAG
from airflow.contrib.operators.bigquery_operator import BigQueryOperator
today_date = datetime.datetime.now().strftime("%Y%m%d")
table_name = 'my_dataset.my_table' + '$' + today_date
with DAG(dag_id='my_dags.my_dag') as dag:
    start = DummyOperator(task_id='start')
    end = DummyOperator(task_id='end')
    sql = """
         SELECT *
         FROM 'another_dataset.another_table'
          """
    bq_query = BigQueryOperator(bql=sql,
                        destination_dataset_table={{ params.t_name }}),
                        task_id='bq_query',
                        bigquery_conn_id='my_bq_connection',
                        use_legacy_sql=False,
                        write_disposition='WRITE_TRUNCATE',
                        create_disposition='CREATE_IF_NEEDED',
                        query_params={'t_name': table_name},
                        dag=dag
                        )
start >> bq_query >> end

所以我做的是创建了一个动态表名变量并传递给BQ运算符。

答案 1 :(得分:0)

这里的主要问题是我无法访问新版本的google云python API,prod正在使用版本0.27.0。 所以,为了完成工作,我做了一件坏事和肮脏的事情:

  • 将查询结果保存在分片表中,让它为table_sharded
  • 获得了table_sharded的架构,让它成为table_schema
  • " SELECT * FROM dataset.table_sharded"个查询保存到提供table_schema
  • 的分区表中

所有这些都是在一个使用钩子的操作符中抽象出来的。钩子负责创建/删除表/分区,获取表模式并在BigQuery上运行查询。

查看code。如果还有其他解决方案,请告诉我。

答案 2 :(得分:0)

使用BigQueryOperator,您可以传递time_partitioning参数,该参数将创建提取时间分区表

bq_cmd = BigQueryOperator (
            task_id=                    "task_id",
            sql=                        [query],
            destination_dataset_table=  destination_tbl,
            use_legacy_sql=             False,
            write_disposition=          'WRITE_TRUNCATE',
            time_partitioning=          {'time_partitioning_type':'DAY'},
            allow_large_results=        True,
            trigger_rule=               'all_success',
            query_params=               query_params,
            dag=                        dag
        )

答案 3 :(得分:0)

from datetime import datetime,timedelta
from airflow import DAG
from airflow.models import Variable
from airflow.contrib.operators.bigquery_operator import BigQueryOperator
from airflow.operators.dummy_operator import DummyOperator

DEFAULT_DAG_ARGS = {
    'owner': 'airflow',
    'depends_on_past': False,
    'retries': 2,
    'retry_delay': timedelta(minutes=10),
    'project_id': Variable.get('gcp_project'),
    'zone': Variable.get('gce_zone'),
    'region': Variable.get('gce_region'),
    'location': Variable.get('gce_zone'),
}

with DAG(
    'test',
    start_date=datetime(2019, 1, 1),
    schedule_interval=None,
    catchup=False,
    default_args=DEFAULT_DAG_ARGS) as dag:

    bq_query = BigQueryOperator(
        task_id='create-partition',
        bql="""SELECT
                * 
                FROM
                `dataset.table_name`""",   -- table from which you want to pull data
        destination_dataset_table='project.dataset.table_name' + '$' + datetime.now().strftime('%Y%m%d'),             -- Auto partitioned table in Bq 
        write_disposition='WRITE_TRUNCATE',
        create_disposition='CREATE_IF_NEEDED',
        use_legacy_sql=False,
    )

我建议在Airflow中使用Variable,并创建所有字段并在DAG中使用。 通过以上代码,分区将添加到Bigquery表中,以显示今天的日期。