2012-11-13 102 views
9

我正在使用燒瓶,sqlalchemy和flask-sqlalchemy。我想用杜松子酒和to_tsvector在postgres中創建一個完整的測試搜索索引。目前,我正在嘗試以下內容。我認爲它與我想要表達的最接近,但不起作用。SQLAlchemy with PostgresSQL and Full Text Search

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"),) 

這引發以下錯誤......

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' 

我也試過

return (Index('idx_content', "content", postgresql_using="gin"),) 

但是,它並沒有Postgres的工作(9.1至少,因爲這是我運行的)期望to_tsvector被調用。這一行創建SQL;

CREATE INDEX content_index ON post USING gin (content) 

而不是我想要的;

CREATE INDEX content_index ON post USING gin(to_tsvector('english', content)) 

我打開了一張票,因爲我認爲這可能是一個錯誤/限制。 http://www.sqlalchemy.org/trac/ticket/2605

+1

什麼是SQLAlchemy版本? – plaes

+0

0.8.0測試版。不過,我也嘗試了0.7.2(我認爲 - 最新的穩定版本)。 – d0ugal

+1

有一個與'column.key'和'column.name'用法相關的修復,應用於0.8.0beta – plaes

回答

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')) 

關於SQLAlchemy錯誤跟蹤器有一些有趣的討論。看起來這是對當前索引定義的限制。基本上,我的要求是允許索引是表達式而不是列名,但目前不支持。此故障單正在跟蹤此功能請求:http://www.sqlalchemy.org/trac/ticket/695。但是,這正在等待開發人員繼續並開展工作(並且已經有一段時間了)。

1

所以在SQLAlchemy的0.9及以上工作的:

class Content(Base,): 
    __tablename__ = 'content' 

    id = sa.Column(sa.Integer, primary_key=True) 

    description = sa.Column(sa.UnicodeText, nullable=False, server_default='') 
    @declared_attr 
    def __table_args__(cls): 
     return (sa.Index('idx_content', 
        sa.sql.func.to_tsvector("english", cls.description), 
        postgresql_using="gin"),) 

值得注意的是,從第一個例子不同的是直接引用列名,而不是在引號所提供的列名,爲不工作。

+0

我在0.9.8上試過這個,但它沒有。打破:'sqlalchemy.exc.ArgumentError:無法將未命名的列添加到列集合' –