简体   繁体   English

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

[英]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.

相关问题 SQLAlchemy:声明性ORM-使用GIST和TSRANGE建立索引 - SQLAlchemy: Declarative ORM - build index using GIST and TSRANGE 如何使用SQLAlchemy声明式ORM在声明的属性上设置索引? - How can I set an index on a declared attribute using SQLAlchemy Declarative ORM? 在sqlalchemy声明式基础中使用多个继承级别 - Using multiple levels of inheritance with sqlalchemy declarative base 高效查询多列SQLAlchemy ORM - Querying multiple columns efficiently SQLAlchemy ORM sqlalchemy orm声明性基类的访问元素 - Accessing Elements of sqlalchemy orm declarative base class 使用ORM,声明式样式和关联对象在SQLAlchemy中递归选择(具有有限深度)关系 - Recursively select (with limited depth) relationships in SQLAlchemy using ORM, declarative style, and Association objects 如何使用 SQLAlchemy Postgres ORM 的声明性基础从字典动态创建具有列名和约束的表? - How to Dynamically Create Tables With Column Names and Constraints From Dictionary Using SQLAlchemy Postgres ORM's Declarative Base? 与多个索引列或索引一起使用groupby时 - When using groupby with multiple index columns or index sqlalchemy:使用声明式和反射式多次连接到同一表 - sqlalchemy: joining to the same table multiple times using declarative and reflection 具有声明性ORM扩展的Flask SQL Alchemy - Flask SQL Alchemy with declarative ORM extension
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM