多列索引时使用声明性 ORM 扩展

根据 文件sqlalchemy.Column类中的注释,我们应该使用类 sqlalchemy.schema.Index来指定包含多列的索引。

但是,这个示例显示了如何通过直接使用 Table 对象来实现这一点,如下所示:

meta = MetaData()
mytable = Table('mytable', meta,
# an indexed column, with index "ix_mytable_col1"
Column('col1', Integer, index=True),


# a uniquely indexed column with index "ix_mytable_col2"
Column('col2', Integer, index=True, unique=True),


Column('col3', Integer),
Column('col4', Integer),


Column('col5', Integer),
Column('col6', Integer),
)


# place an index on col3, col4
Index('idx_col34', mytable.c.col3, mytable.c.col4)

如果我们使用声明性 ORM 扩展,我们应该如何做呢?

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

我想要一个关于“ a”和“ b”列的索引。

56724 次浏览

这些只是 Column对象,index = True 标志正常工作:

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

如果你想要一个复合索引,同样的,Table在这里和往常一样,你只需要不声明它,所有的工作原理都是一样的(确保你在最近的0.6或0.7为声明性 A.a 包装器被解释为一个 Column在类声明完成之后) :

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)

在0.7中,Index也可以出现在 Table参数中,使用声明式的参数可以通过 __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"), )

完成@zzzeek 的 回答

如果您希望使用 DESC 添加一个复合索引,并使用 ORM 声明方法,则可以执行以下操作。

此外,我还在努力阅读 SQLAlchemy 的 功能指数文档,试图找到替代 mytable.c.somecol的方法。

from sqlalchemy import Index


Index('someindex', mytable.c.somecol.desc())

我们可以只使用 model 属性并在其上调用 .desc():

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),
)

如果你使用 Alembic,我使用 Flask-Migrate,它会生成类似于:

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 ###

最后,在 PostgreSQL 数据库中应该有以下表和索引:

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)