SQLAlchemy与PostgreSQL和全文搜索

d0u*_*gal 11 python postgresql sqlalchemy flask

我正在使用烧瓶,sqlalchemy和flask-sqlalchemy.我想在postgres中使用gin和to_tsvector创建一个完整的测试搜索索引.目前,我正在尝试以下方面.我认为它是我最接近我想要表达的东西,但是不起作用.

from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.schema import Index
from sqlalchemy.sql.expression import func

from app import db


class Post(db.Model):

    id = db.Column(db.Integer, primary_key=True)
    added = db.Column(db.DateTime, nullable=False)
    pub_date = db.Column(db.DateTime, nullable=True)
    content = db.Column(db.Text)

    @declared_attr
    def __table_args__(cls):
        return (Index('idx_content', func.to_tsvector("english", "content"), postgresql_using="gin"), )
Run Code Online (Sandbox Code Playgroud)

这会引发以下错误......

Traceback (most recent call last):
  File "./manage.py", line 5, in <module>
    from app import app, db
  File "/vagrant/app/__init__.py", line 36, in <module>
    from pep.models import *
  File "/vagrant/pep/models.py", line 8, in <module>
    class Post(db.Model):
  File "/home/vagrant/.virtualenvs/pep/local/lib/python2.7/site-packages/flask_sqlalchemy.py", line 477, in __init__
    DeclarativeMeta.__init__(self, name, bases, d)
  File "/home/vagrant/.virtualenvs/pep/local/lib/python2.7/site-packages/sqlalchemy/ext/declarative/api.py", line 48, in __init__
    _as_declarative(cls, classname, cls.__dict__)
  File "/home/vagrant/.virtualenvs/pep/local/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 222, in _as_declarative
    **table_kw)
  File "/home/vagrant/.virtualenvs/pep/local/lib/python2.7/site-packages/sqlalchemy/schema.py", line 326, in __new__
    table._init(name, metadata, *args, **kw)
  File "/home/vagrant/.virtualenvs/pep/local/lib/python2.7/site-packages/sqlalchemy/schema.py", line 393, in _init
    self._init_items(*args)
  File "/home/vagrant/.virtualenvs/pep/local/lib/python2.7/site-packages/sqlalchemy/schema.py", line 63, in _init_items
    item._set_parent_with_dispatch(self)
  File "/home/vagrant/.virtualenvs/pep/local/lib/python2.7/site-packages/sqlalchemy/events.py", line 235, in _set_parent_with_dispatch
    self._set_parent(parent)
  File "/home/vagrant/.virtualenvs/pep/local/lib/python2.7/site-packages/sqlalchemy/schema.py", line 2321, in _set_parent
    ColumnCollectionMixin._set_parent(self, table)
  File "/home/vagrant/.virtualenvs/pep/local/lib/python2.7/site-packages/sqlalchemy/schema.py", line 1978, in _set_parent
    self.columns.add(col)
  File "/home/vagrant/.virtualenvs/pep/local/lib/python2.7/site-packages/sqlalchemy/sql/expression.py", line 2391, in add
    self[column.key] = column
  File "/home/vagrant/.virtualenvs/pep/local/lib/python2.7/site-packages/sqlalchemy/sql/expression.py", line 2211, in __getattr__
    key)
AttributeError: Neither 'Function' object nor 'Comparator' object has an attribute 'key'
Run Code Online (Sandbox Code Playgroud)

我也试过了

return (Index('idx_content', "content", postgresql_using="gin"), )
Run Code Online (Sandbox Code Playgroud)

但是,它不能用作postgres(至少9.1,因为我运行的那个)期望调用to_tsvector.这一行创建了SQL;

CREATE INDEX content_index ON post USING gin (content)
Run Code Online (Sandbox Code Playgroud)

而不是我想要的;

CREATE INDEX content_index ON post USING gin(to_tsvector('english', content))
Run Code Online (Sandbox Code Playgroud)

我打开了一张票,因为我认为这可能是一个错误/限制.http://www.sqlalchemy.org/trac/ticket/2605

d0u*_*gal 4

现在我已经添加了以下几行来手动执行此操作,但我更愿意使用“正确的”SQLAlchemy 方法(如果有)。

create_index = DDL("CREATE INDEX idx_content ON pep USING gin(to_tsvector('english', content));")
event.listen(Pep.__table__, 'after_create', create_index.execute_if(dialect='postgresql'))
Run Code Online (Sandbox Code Playgroud)

关于 SQLAlchemy 错误跟踪器有一些有趣的讨论。看起来这是当前索引定义的限制。基本上,我的要求是允许索引是表达式而不仅仅是列名,但目前不支持。此票证正在跟踪此功能请求:http://www.sqlalchemy.org/trac/ticket/695。然而,这正在等待开发人员继续推进并完成工作(并且已经有一段时间了)。