2016-04-03 20 views
2

Web forumundaki verileri kazıyarak Scrapy kullanıyorum. Bu verileri SQLAlchemy kullanarak bir PostgreSQL veritabanında saklıyorum. Tablo ve sütunlar iyi oluşturulur, ancak SQLAlchemy'nin sütunlardan birinde bir dizin oluşturmasını sağlayamıyorum. Cin kullanarak bir trigram indeksi (pg_trgm) oluşturmaya çalışıyorum.Scrub için SQLAlchemy kullanarak pg_trgm dizini nasıl oluşturulur?

bu indeks yaratacak Postgresql kodudur:

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

benim models.py dosyasına eklemiş SQLAlchemy kodudur:

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

benim modellerine bu çizgiyi eklemiş .py ama postgresql'de kontrol ettiğimde indeks hiç oluşturulmadı.

Aşağıda, tam models.py ve pipelines.py dosyalarım var. Bu kadarı yanlış mı yapıyorum?

Herhangi bir yardım büyük ölçüde takdir edilecektir!

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 

cevap

3

Index tanım dolaylı tarafından oluşturuldu Table "tablosuna", bir referansı yoktur text ifadesini kullandığından bildirim sınıfı forumDB. Böyle ifade olarak bir Column veya bir kısmı türevini kullanarak mukayese edelim:

Index('some_index_idx', forumDB.title) 

indeks tablosu ve etrafında diğer yolu hakkında bilecek Yukarıdaki tanımda.

Bu, sizin durumunuzda ne anlama gelir Table "tablo" böyle bir dizinin var olduğu hakkında hiçbir fikri yoktur. Bunu deklarasyon sınıfının bir özelliği olarak eklemek yanlış bir yoldur. Kesin olarak oluşturulan Table örneğine geçirilmelidir. özelliği __table_args__ sadece içindir: bir yerde modifikasyon ile

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) bir çağrı ile sonuçlanmıştır: SQLAlchemy bir Operator Class referans

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

Teşekkür ederiz! Bu mükemmel çalıştı! –

2

uygun bir şekilde (örneğin, gin_trgm_ops gibi) postgresql_ops parametresini kullanmaktır. Bu, aynı zamanda, alembic gibi araçların, otomatik olarak geçiş oluştururken nasıl kullanıldığını anlamasına da olanak tanır.

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