在 PostgreSQL 上使用 SQLAlchemy 创建全文搜索索引

新手上路,请多包涵

我需要使用 SQLAlchemy 在 Python 中创建一个 PostgreSQL 全文搜索索引。这是我想要的 SQL:

 CREATE TABLE person ( id INTEGER PRIMARY KEY, name TEXT );
CREATE INDEX person_idx ON person USING GIN (to_tsvector('simple', name));

现在如何在使用 ORM 时使用 SQLAlchemy 执行第二部分:

 class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)

原文由 Markus Meskanen 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.8k
2 个回答

您可以在 __table_args__ Index 创建索引。我还使用一个函数来创建 ts_vector 以使其在需要多个字段时更加整洁和可重用。像下面这样的东西:

 from sqlalchemy.dialects import postgresql

def create_tsvector(*args):
    exp = args[0]
    for e in args[1:]:
        exp += ' ' + e
    return func.to_tsvector('english', exp)

class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)

    __ts_vector__ = create_tsvector(
        cast(func.coalesce(name, ''), postgresql.TEXT)
    )

    __table_args__ = (
        Index(
            'idx_person_fts',
            __ts_vector__,
            postgresql_using='gin'
        )
    )


更新: 使用索引的示例查询(根据评论更正):

 people = Person.query.filter(Person.__ts_vector__.match(expressions, postgresql_regconfig='english')).all()

原文由 sharez 发布,翻译遵循 CC BY-SA 4.0 许可协议

@sharez 的答案非常有用(尤其是当您需要连接索引中的列时)。对于希望在单个列上创建 tsvector GIN 索引的任何人,您可以使用以下方法简化原始答案方法:

 from sqlalchemy import Column, Index, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql import func

Base = declarative_base()

class Example(Base):
    __tablename__ = 'examples'

    id = Column(Integer, primary_key=True)
    textsearch = Column(String)

    __table_args__ = (
        Index(
            'ix_examples_tsv',
            func.to_tsvector('english', textsearch),
            postgresql_using='gin'
            ),
        )

Note that the comma following Index(...) in __table_args__ is not a style choice, the value of __table_args__ must be a tuple, dictionary, or None

如果您确实需要在多个列上创建 tsvector GIN 索引,这是使用 text() 的另一种方法。

 from sqlalchemy import Column, Index, Integer, String, text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql import func

Base = declarative_base()

def to_tsvector_ix(*columns):
    s = " || ' ' || ".join(columns)
    return func.to_tsvector('english', text(s))

class Example(Base):
    __tablename__ = 'examples'

    id = Column(Integer, primary_key=True)
    atext = Column(String)
    btext = Column(String)

    __table_args__ = (
        Index(
            'ix_examples_tsv',
            to_tsvector_ix('atext', 'btext'),
            postgresql_using='gin'
            ),
        )

原文由 benvc 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题