首页 > 解决方案 > 如何将模型的标签列表添加到弹性搜索索引?

问题描述

我有使用flask sqlalchemy 的数据库模型,并且我正在尝试将标签添加到我的elasticsearch 索引中。非关系列值(如“名称”或“时间戳”)可以很好地添加。但是,当我尝试添加或更新其模型实例时,关联表中的数据(如标签)会导致错误(如下所述*)。

调用后,会调用db.session.commit()下面的可搜索模型 mixin 方法models.py

@classmethod
def after_commit(cls, session):
    for obj in session._changes['add']:
        if isinstance(obj, SearchableMixin):
            add_to_index(obj.__tablename__, obj)
    # cases for 'update' and 'delete' stages ... 

我的标签出现在模型类中,如下所示(project_tag_map关联表在哪里):

tags = db.relationship(
        'Tag', secondary=project_tag_map,
        backref=db.backref('project_tag_map', lazy='dynamic'), lazy='dynamic')

接下来after_commit(),这就是魔法发生的地方,在search.py

def add_to_index(index, model):
    payload = {}
    for field in model.__searchable__:
        if field == 'tags':
            tags = model.tags
            payload[field] = [t.name for t in tags]
        else:
            payload[field] = getattr(model, field)
    ...

*当它开始添加标签(在t.name列表理解中)时,我得到

sqlalchemy.exc.InvalidRequestError: This session is in 'committed' state; no further SQL can be emitted within this transaction.

我试过用getattr以防万一替换它,这也不起作用。

我找到了一种解决方法,方法是在重新索引模型本身时仅将此标签列表添加到有效负载中。search.py即,仅在调用以下函数时执行有问题的行:

@classmethod
def reindex(cls):
    for obj in cls.query:
        add_to_index(cls.__tablename__, obj,stage='reindex')

不过,这似乎很老套,我不想每次添加标签后都重新索引。

标签: pythonelasticsearchsqlalchemy

解决方案


推荐阅读