![](/img/trans.png)
[英]Create a Full Text Search index with SQLAlchemy on PostgreSQL
[英]SQLAlchemy with PostgreSQL and Full Text Search
我正在使用燒瓶,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"), )
這會引發以下錯誤......
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
現在我已經添加了以下行來手動執行,但我更傾向於“正確的”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 bug跟蹤器的一些有趣的討論。 看起來這是當前索引定義的限制。 基本上,我的要求是允許索引是表達式而不僅僅是列名,但目前不支持。 此票證正在跟蹤此功能請求: http : //www.sqlalchemy.org/trac/ticket/695 。 然而,這正在等待開發人員推進並完成工作(並且已經有一段時間了)。
因此在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"), )
值得注意的是,與第一個示例的不同之處在於對列名的直接引用,而不是引號中提供的列名,因為它不起作用。
在我正在努力創建一些單列和多列tsvector GIN索引時,遇到這個老問題。 對於正在尋找使用列名的字符串表示來創建這些索引的簡單方法的任何人,這里有一種使用SQLAlchemy 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'
),
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.