2016-04-03 11 views
2

私はScrapyを使用してWebフォーラムからデータをスクラップしています。 SQLAlchemyを使用してこのデータをPostgreSQLデータベースに保存しています。しかし、テーブルとカラムはうまく作成されますが、SQLAlchemyにカラムの1つにインデックスを作成させることはできません。私はginを使ってtrigramインデックス(pg_trgm)を作成しようとしています。SQLAlchemyを使用して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定義は、それが暗黙のうちにによって作成されたTable "テーブル"、への参照を持っていないtext式を使用していますので、宣言的クラスforumDB。式としてColumnを使用することの比較、またはその一部の派生物、このような:

Index('some_index_idx', forumDB.title) 

上記の定義では、インデックスは、テーブルと他の方法で回避について知っているだろう。

あなたのケースでこれが意味するのは、Table "テーブル"にはそのようなインデックスが存在しないということです。それを宣言的クラスの属性として追加するのは間違った方法です。暗黙的に作成されたTableインスタンスに渡す必要があります。属性__table_args__はちょうどそのためにされています

> \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

(例えばgin_trgm_opsなど)SQLAlchemyの中Operator Classを参照する適切な方法を:場所に変更して

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)への呼び出しは、以下のような結果にpostgresql_opsパラメータを使用することです。これにより、alembicのようなツールで、自動生成マイグレーションの使用方法を理解することもできます。

Index('description_idx', 
     'description', postgresql_using='gin', 
     postgresql_ops={ 
      'description': 'gin_trgm_ops', 
     }) 
関連する問題