使用WhooshAlchemy和连接表继承

时间:2015-10-25 18:23:29

标签: flask sqlalchemy flask-sqlalchemy whoosh

我目前有类似的内容(取自SQLAlchemy documentation):

class Employee(Base):
    __tablename__ = 'employee'
    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    type = Column(String(50))

    __mapper_args__ = {
        'polymorphic_identity':'employee',
        'polymorphic_on':type
    }

class Engineer(Employee):
    __tablename__ = 'engineer'
    id = Column(Integer, ForeignKey('employee.id'), primary_key=True)
    engineer_name = Column(String(30))

    __mapper_args__ = {
        'polymorphic_identity':'engineer',
    }

class Manager(Employee):
    __tablename__ = 'manager'
    id = Column(Integer, ForeignKey('employee.id'), primary_key=True)
    manager_name = Column(String(30))

    __mapper_args__ = {
        'polymorphic_identity':'manager',
    }

使用WhooshAlchemy,我想分别搜索name列,engineer_namemanager_name分别为EngineerManager

我已尝试将包含其列的单独__searchable__列表放入每个类中,但这会给我以下错误:

whoosh.fields.UnknownFieldError: No field named 'name' in <Schema: ['id', 'engineer_name']>

我还尝试将__searchable__列表放入每个只包含在该特定类中定义的列的列表,但是当我在查询中使用whoosh_search时,这根本没有给我任何结果,尽管有有效的搜索字词应至少返回1个结果。

最简单的方法是什么?

2 个答案:

答案 0 :(得分:0)

您必须明确定义可以处理所有这些模式的模式。 您将覆盖继承类上的可搜索字段。

class Employee(Base):
    __tablename__ = 'employee'
    __searchable__ = ['name']
    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    type = Column(String(50))

    __mapper_args__ = {
        'polymorphic_identity':'employee',
        'polymorphic_on':type
    }

class Engineer(Employee):
    __tablename__ = 'engineer'
    __searchable__ = ['name', 'engineer_name']
    id = Column(Integer, ForeignKey('employee.id'), primary_key=True)
    engineer_name = Column(String(30))

    __mapper_args__ = {
        'polymorphic_identity':'engineer',
    }

class Manager(Employee):
    __tablename__ = 'manager'
    __searchable__ = ['name', 'manager_name ']
    id = Column(Integer, ForeignKey('employee.id'), primary_key=True)
    manager_name = Column(String(30))

    __mapper_args__ = {
        'polymorphic_identity':'manager',
    }

然后在构建索引时:

from whooshalchemy import IndexService
from whoosh.fields import Schema, TEXT

# However your app initializes it
index_service = IndexService(config=app.config, session=db.session)  

my_schema = Schema(name=TEXT, engineer_name=TEXT, manager_name=TEXT)
index = index_service.index_for_model_class(model)

with index.writer() as writer:

    for engineer in Engineer.query.all():
        index_attrs = {}
        for field in Engineer.__searchable__:
            index_attrs[field] = str(getattr(engineer, field))

        index_attrs["id"] = engineer.id

        writer.add_document(**index_attrs)

    for manager in Manager.query.all():
        index_attrs = {}
        for field in Manager.__searchable__:
            index_attrs[field] = str(getattr(manager, field))

        index_attrs["id"] = manager.id

        writer.add_document(**index_attrs)

后来搜索时:

engineer_search_results = Engineer.search_query("SomeText").all()
manager_search_results = Manager.search_query("SomeText").all()

答案 1 :(得分:-2)

烧瓶 - who os不得

如果您也使用烧瓶,您可以尝试我的名为Flask-WhooshAlchemyPlus的flask_whooshalchemy fork,它可以索引继承的模型

您可以为每个模型添加可搜索自己的字段名称

我只需将代码粘贴到此处

def _get_whoosh_schema_and_primary_key(model, analyzer):
    schema = {}
    primary = None
    searchable = set(model.__searchable__)

    for field in model.__table__.columns:
        if field.primary_key:
            schema[field.name] = whoosh.fields.ID(stored=True, unique=True)
            primary = field.name

        if field.name in searchable and isinstance(field.type,
                                               (sqlalchemy.types.Text,
                                                sqlalchemy.types.String,
                                                sqlalchemy.types.Unicode)):
            schema[field.name] = whoosh.fields.TEXT(
                analyzer=analyzer, vector=True)

    for parent_class in model.__bases__:
        if hasattr(parent_class, "_sa_class_manager"):
            if parent_class.__searchable__:
                for i in set(parent_class.__searchable__):
                    if hasattr(parent_class, i):
                        schema[i] = whoosh.fields.TEXT(
                            analyzer=analyzer, vector=True)

    return Schema(**schema), primary