As of January 1, 2020 this library no longer supports Python 2 on the latest released version. Library versions released prior to that date will continue to be available. For more information please visit Python 2 support on Google Cloud.

Working with BigQuery STRUCT dataΒΆ

The BigQuery STRUCT data type provided data that are collections of named fields.

sqlalchemy-bigquery provided a STRUCT type that can be used to define tables with STRUCT columns:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String, Integer, Float
from sqlalchemy_bigquery import STRUCT

Base = declarative_base()

class Car(Base):
    __tablename__ = "Cars"

    model = Column(String, primary_key=True)
    engine = Column(
        STRUCT(
            cylinder=STRUCT(("count", Integer),
                            ("compression", Float)),
            horsepower=Integer)
        )

STRUCT types can be nested, as in this example. Struct fields can be defined in two ways:

  • Fields can be provided as keyword arguments, as in the cylinder and horsepower fields in this example.

  • Fields can be provided as name-type tuples provided as positional arguments, as with the count and compression fields in this example.

STRUCT columns are automatically created when existing database tables containing STRUCT columns are introspected.

Struct data are represented in Python as Python dictionaries:

from sqlalchemy.orm import sessionmaker

Session = sessionmaker(bind=engine)
session = Session()

sebring = Car(model="Sebring",
              engine=dict(
                  cylinder=dict(
                      count=6,
                      compression=18.0),
                  horsepower=235))
townc = Car(model="Town and Counttry",
            engine=dict(
                cylinder=dict(
                    count=6,
                    compression=16.0),
                horsepower=251))
xj8 = Car(model="XJ8",
          engine=dict(
              cylinder=dict(
                  count=8,
                  compression=10.75),
              horsepower=575))

session.add_all((sebring, townc, xj8))
session.commit()

When querying struct fields, you can use attribute access syntax:

sixes = session.query(Car).filter(Car.engine.cylinder.count == 6)

or mapping access:

sixes = session.query(Car).filter(Car.engine["cylinder"]["count"] == 6)

and field names are case insensitive:

sixes = session.query(Car).filter(Car.engine.CYLINDER.COUNT == 6)

When using attribute-access syntax, field names may conflict with column attribute names. For example SQLAlchemy columns have name and type attributes, among others. When accessing a field whose name conflicts with a column attribute name, either use mapping access, or spell the field name with upper-case letters.