如何使用SQLAlchemy for Scrapy创建pg_trgm索引?

时间:2016-04-03 18:10:04

标签: python postgresql indexing sqlalchemy scrapy

我正在使用Scrapy从网络论坛中抓取数据。我使用SQLAlchemy将这些数据存储在PostgreSQL数据库中。表和列创建很好,但是,我无法让SQLAlchemy在其中一列上创建索引。我正在尝试使用gin创建一个三元组索引(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')

我已将此行添加到我的models.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

2 个答案:

答案 0 :(得分:7)

在SQLAlchemy中引用Operator Class的正确方法(例如> library(stringr) > ss <- c('jobs?search=term1&location=&distance=10+page=2','jobs?search=term1+term2&location=ca&distance=30','jobs?search=term1+term2+term3&location=nyc&distance=25') > results <- str_match(ss, "[&?]search=([^&+]+)(?:&|$)") > results[,2] [1] "term1" NA NA > )是使用gin_trgm_ops参数。这也可以让alembic等工具了解在自动生成迁移时如何使用它。

postgresql_ops

答案 1 :(得分:5)

由于Index定义使用text表达式,因此它没有引用Table&#34;表&#34;,它已由声明性类{{1}隐式创建}}。相比之下,使用forumDB作为表达式或其衍生物,如下所示:

Column

在上面的定义中,索引会知道表格,反之亦然。

在您的情况下,这意味着Index('some_index_idx', forumDB.title) &#34;表&#34;不知道这样的索引存在。将它添加为声明性类的属性是错误的方法。它应该传递给隐式创建的Table实例。属性__table_args__仅适用于此:

Table

修改到位后,调用class forumDB(DeclarativeBase): __tablename__ = "table" # Note: This used to use `text('description gin_trgm_ops')` instead of the # `postgresql_ops` parameter, which should be used. __table_args__ = ( Index('description_idx', "description", postgresql_ops={"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)