2016-04-03 61 views
2

我正在使用Scrapy從網絡論壇中抓取數據。我使用SQLAlchemy將這些數據存儲在PostgreSQL數據庫中。表和列創建很好,但是,我無法讓SQLAlchemy在其中一列上創建索引。我正在嘗試使用杜松子酒創建trigram索引(pg_trgm)。如何使用SQLAlchemy for Scrapy創建pg_trgm索引?

PostgreSQL的代碼,將創建這個索引:

CREATE INDEX description_idx ON table USING gin (description gin_trgm_ops); 

我已經加入到我的models.py文件中的SQLAlchemy的代碼是:

desc_idx = Index('description_idx', text("description gin_trgm_ops"), postgresql_using='gin') 

我已經加入這一行我的模型.py但是當我檢查postgresql時,索引從未創建。

下面是我的完整models.py和pipelines.py文件。我有關這一切都錯了嗎?

任何幫助將不勝感激!

models.py:

from sqlalchemy import create_engine, Column, Integer, String, DateTime, Index, text 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.engine.url import URL 
import settings 

DeclarativeBase = declarative_base() 
def db_connect(): 
return create_engine(URL(**settings.DATABASE)) 

def create_forum_table(engine): 
    DeclarativeBase.metadata.create_all(engine)  


class forumDB(DeclarativeBase): 
    __tablename__ = "table" 

    id = Column(Integer, primary_key=True) 
    title = Column('title', String) 
    desc = Column('description', String, nullable=True) 
    desc_idx = Index('description_idx', text("description gin_trgm_ops"), postgresql_using='gin') 

pipelines.py
from scrapy.exceptions import DropItem 
from sqlalchemy.orm import sessionmaker 
from models import forumDB, db_connect, create_forum_table 


class ScrapeforumToDB(object): 
def __init__(self): 
    engine = db_connect() 
    create_forum_table(engine) 
    self.Session = sessionmaker(bind=engine) 

def process_item(self, item, spider): 
    session = self.Session() 
    forumitem = forumDB(**item) 

    try: 
     session.add(forumitem) 
     session.commit() 
    except: 
     session.rollback() 
     raise 
    finally: 
     session.close() 

    return item 

回答

3

由於Index定義使用text表達它具有到Table 「表」,已經由被隱式地創建任何引用聲明類forumDB。與此相比,使用作爲Column表達,或它的某些衍生物,例如:

Index('some_index_idx', forumDB.title) 

在上述定義中的索引將瞭解表和周圍的其他方式。

這意味着你的情況是Table「表」不知道這樣的索引存在。將它作爲聲明類的屬性添加是錯誤的方法。它應該被傳遞給隱式創建的Table實例。屬性__table_args__只是爲:

class forumDB(DeclarativeBase): 

    __tablename__ = "table" 
    __table_args__ = (
     Index('description_idx', text("description gin_trgm_ops"), postgresql_using='gin'), 
    ) 

    id = Column(Integer, primary_key=True) 
    title = Column('title', String) 
    desc = Column('description', String, nullable=True) 

到位後修飾,以create_forum_table(engine)呼叫導致:

> \d "table" 
           Table "public.table" 
    Column |  Type  |      Modifiers      
-------------+-------------------+---------------------------------------------------- 
id   | integer   | not null default nextval('table_id_seq'::regclass) 
title  | character varying | 
description | character varying | 
Indexes: 
    "table_pkey" PRIMARY KEY, btree (id) 
    "description_idx" gin (description gin_trgm_ops) 
+0

謝謝!這工作完美! –

2

的正確方法引用在SQLAlchemy的一個Operator Class(如gin_trgm_ops)是使用postgresql_ops參數。這也將允許像alembic這樣的工具瞭解如何在自動生成遷移時使用它。

Index('description_idx', 
     'description', postgresql_using='gin', 
     postgresql_ops={ 
      'description': 'gin_trgm_ops', 
     })