[英]Multiple columns index when using the declarative ORM extension of sqlalchemy
According to the documentation and the comments in the sqlalchemy.Column
class, we should use the class sqlalchemy.schema.Index
to specify an index that contains multiple columns.根据
sqlalchemy.Column
class 中的文档和注释,我们应该使用 class sqlalchemy.schema.Index
来指定包含多个列的索引。
However, the example shows how to do it by directly using the Table object like this:但是,该示例显示了如何通过直接使用表 object 来执行此操作,如下所示:
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)
How should we do it if we use the declarative ORM extension?如果我们使用声明式 ORM 扩展,我们应该怎么做?
class A(Base):
__tablename__ = 'table_A'
id = Column(Integer, , primary_key=True)
a = Column(String(32))
b = Column(String(32))
I would like an index on column "a" and "b".我想要列“a”和“b”的索引。
those are just Column
objects, index=True flag works normally:这些只是
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)
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 Aa wrapper to be interpreted as a Column
after the class declaration is complete):如果您想要一个复合索引,
Table
再次像往常一样出现在这里,您不必声明它,一切都一样(确保您在最近的 0.6 或 0.7 上,声明性 Aa 包装器将被解释为class 声明完成后的一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)
In 0.7 the Index
can be in the Table
arguments too, which with declarative is via __table_args__
:在 0.7 中,
Index
也可以在Table
arguments 中,声明式是通过__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"), )
To complete @zzzeek's answer .完成@zzzeek 的回答。
If you like to add a composite index with DESC and use the ORM declarative method you can do as follows.如果您想使用 DESC 添加复合索引并使用 ORM 声明式方法,您可以执行以下操作。
Furthermore, I was struggling with the Functional Indexes documentation of SQSAlchemy, trying to figure out a how to substitute mytable.c.somecol
.此外,我在 SQSAlchemy 的功能索引文档中苦苦挣扎,试图找出如何替换
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:我们可以只使用 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),
)
If you use Alembic, I'm using Flask-Migrate, it generates something like:如果您使用 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 ###
Finally you should have the following table and indexes in your PostgreSQL database:最后,您的 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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.