Sqlalchemy'nin bildirimsel ORM uzantısını kullanırken çoklu sütun indeksi


97

Göre belgelerde ve yorumlarla sqlalchemy.Columnsınıfında, biz sınıfını kullanmalısınız sqlalchemy.schema.Indexbirden çok sütun içeren bir dizin belirtmek için.

Bununla birlikte, örnek, doğrudan aşağıdaki gibi Table nesnesini kullanarak bunun nasıl yapılacağını gösterir:

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)

Bildirimsel ORM uzantısını kullanırsak bunu nasıl yapmalıyız?

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

"A" ve "b" sütunlarında bir dizin istiyorum.


1
Soru, birden çok sütunda birden çok dizin mi yoksa tek bir dizin mi istediğiniz konusunda biraz belirsiz (ve ben onu düzenlemeden önce daha karışıktı - başlangıçta hoş bir şekilde "birden çok dizin içeren bir dizin" istedi ). Ama ne olursa olsun, zzzeek'in cevabı her iki durumu da ele aldığından sanırım.
Mark Amery

Yanıtlar:


144

bunlar sadece Columnnesnelerdir, index = True flag normal şekilde çalışır:

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

Bileşik bir indeks istiyorsanız, yine Tableburada her zamanki gibi mevcutsa, bunu beyan etmeniz gerekmez, her şey aynı şekilde çalışır (bildirimsel Aa sarmalayıcısının bir Columnsınıf beyanı tamamlandıktan sonra):

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'de, bildirimsel ile şu yolla olan argümanlarda da Indexolabilir :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"), )

1
Teşekkürler, ben 0,7 olarak güncellenen ve kullanan table_args cezası işleri
yorjo

7
Şu anda benim yaptığım gibi table_args için bir sözlüğünüz varsa ne olur? table_args = { 'mysql_engine': 'InnoDB'nin'}
Nick Holden


8
Yapabileceğim sanırım Yani table_args = (Endeks ( 'my_index', "a", "b") { 'mysql_engine': 'InnoDB'nin'})
Nick Holden

1
@RyanChou docs.sqlalchemy.org/en/latest/orm/extensions/declarative/… "Anahtar sözcük argümanları, son argümanı sözlük olarak belirterek yukarıdaki formla belirtilebilir"
zzzeek

13

@ Zzzeek'in cevabını tamamlamak için .

DESC ile bileşik bir dizin eklemek ve ORM bildirim yöntemini kullanmak isterseniz, aşağıdaki işlemleri yapabilirsiniz.

Dahası, SQSAlchemy'nin Fonksiyonel Dizinler dokümantasyonuyla mücadele ediyor, nasıl değiştirileceğini bulmaya çalışıyordum mytable.c.somecol.

from sqlalchemy import Index

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

Sadece model özelliğini kullanabilir ve çağırabiliriz .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 kullanıyorsanız, Flask-Migrate kullanıyorum, aşağıdaki gibi bir şey oluşturur:

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

Son olarak, PostgreSQL veritabanınızda aşağıdaki tablo ve dizinlere sahip olmalısınız:

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.