Multiple columns index when using the declarative ORM extension of sqlalchemy

后端 未结 2 1810
小鲜肉
小鲜肉 2021-01-30 02:45

According to the documentation and the comments in the sqlalchemy.Column class, we should use the class sqlalchemy.schema.Index to specify an index tha

相关标签:
2条回答
  • 2021-01-30 03:20

    those are just Column objects, index=True flag works normally:

    class A(Base):
        __tablename__ = 'table_A'
        id = Column(Integer, primary_key=True)
        a = Column(String(32), index=True)
        b = Column(String(32), index=True)
    

    if you'd like a composite index, again Table is present here as usual you just don't have to declare it, everything works the same (make sure you're on recent 0.6 or 0.7 for the declarative A.a wrapper to be interpreted as a Column after the class declaration is complete):

    class A(Base):
        __tablename__ = 'table_A'
        id = Column(Integer, primary_key=True)
        a = Column(String(32))
        b = Column(String(32))
    
    Index('my_index', A.a, A.b)
    

    In 0.7 the Index can be in the Table arguments too, which with declarative is via __table_args__:

    class A(Base):
        __tablename__ = 'table_A'
        id = Column(Integer, primary_key=True)
        a = Column(String(32))
        b = Column(String(32))
        __table_args__ = (Index('my_index', "a", "b"), )
    
    0 讨论(0)
  • 2021-01-30 03:38

    To complete @zzzeek's answer.

    If you like to add a composite index with DESC and use the ORM declarative method you can do as follows.

    Furthermore, I was struggling with the Functional Indexes documentation of SQSAlchemy, trying to figure out a how to substitute mytable.c.somecol.

    from sqlalchemy import Index
    
    Index('someindex', mytable.c.somecol.desc())
    

    We can just use the model property and call .desc() on it:

    from flask_sqlalchemy import SQLAlchemy
    
    db = SQLAlchemy()
    
    class GpsReport(db.Model):
        __tablename__ = 'gps_report'
    
        id = db.Column(db.Integer, db.Sequence('gps_report_id_seq'), nullable=False, autoincrement=True, server_default=db.text("nextval('gps_report_id_seq'::regclass)"))
    
        timestamp = db.Column(db.DateTime, nullable=False, primary_key=True)
    
        device_id = db.Column(db.Integer, db.ForeignKey('device.id'), primary_key=True, autoincrement=False)
        device = db.relationship("Device", back_populates="gps_reports")
    
    
        # Indexes
    
        __table_args__ = (
            db.Index('gps_report_timestamp_device_id_idx', timestamp.desc(), device_id),
        )
    

    If you use Alembic, I'm using Flask-Migrate, it generates something like:

    from alembic import op  
    import sqlalchemy as sa
    # Added manually this import
    from sqlalchemy.schema import Sequence, CreateSequence
    
    
    def upgrade():
        # ### commands auto generated by Alembic - please adjust! ###
        # Manually added the Sequence creation
        op.execute(CreateSequence(Sequence('gps_report_id_seq')))
    
        op.create_table('gps_report',
        sa.Column('id', sa.Integer(), server_default=sa.text("nextval('gps_report_id_seq'::regclass)"), nullable=False),
        sa.Column('timestamp', sa.DateTime(), nullable=False))
        sa.Column('device_id', sa.Integer(), autoincrement=False, nullable=False),
        op.create_index('gps_report_timestamp_device_id_idx', 'gps_report', [sa.text('timestamp DESC'), 'device_id'], unique=False)
    
    
    def downgrade():
        # ### commands auto generated by Alembic - please adjust! ###
        op.drop_index('gps_report_timestamp_device_id_idx', table_name='gps_report')
        op.drop_table('gps_report')
    
        # Manually added the Sequence removal
        op.execute(sa.schema.DropSequence(sa.Sequence('gps_report_id_seq'))) 
        # ### end Alembic commands ###
    

    Finally you should have the following table and indexes in your PostgreSQL database:

    psql> \d gps_report;
                                               Table "public.gps_report"
         Column      |            Type             | Collation | Nullable |                Default                 
    -----------------+-----------------------------+-----------+----------+----------------------------------------
     id              | integer                     |           | not null | nextval('gps_report_id_seq'::regclass)
     timestamp       | timestamp without time zone |           | not null | 
     device_id       | integer                     |           | not null | 
    Indexes:
        "gps_report_pkey" PRIMARY KEY, btree ("timestamp", device_id)
        "gps_report_timestamp_device_id_idx" btree ("timestamp" DESC, device_id)
    Foreign-key constraints:
        "gps_report_device_id_fkey" FOREIGN KEY (device_id) REFERENCES device(id)
    
    0 讨论(0)
提交回复
热议问题