当具有给定属性的相关模型不存在时,SQLAlchemy查询模型

时间:2018-04-25 13:02:33

标签: python sqlalchemy flask-sqlalchemy

我有三个模型(注意这是在Flask-SQLAlchemy中完成的,但是如果你只能为vanilla SQLAlchemy写一个答案,那对我来说没问题。)为了清楚起见,删除了不相关的字段。

class KPI(db.Model):
    __tablename__ = 'kpis'

    id = db.Column(db.Integer, primary_key=True)
    identifier = db.Column(db.String(length=50))


class Report(db.Model):
    __tablename__ = 'reports'

    id = db.Column(db.Integer, primary_key=True)


class ReportKPI(db.Model):
    report_id = db.Column(db.Integer, db.ForeignKey('reports.id'), primary_key=True)
    kpi_id = db.Column(db.Integer, db.ForeignKey('kpis.id'), primary_key=True)

    report = db.relationship('Report', backref=db.backref('values'))
    kpi = db.relationship('KPI')

我的目标是查找不衡量特定Report的所有KPI个对象(即没有ReportKPIKPI关系identifier的对象设置为特定值。)

我的一次尝试看起来像

Report.query \
      .join(ReportKPI) \
      .join(KPI) \
      .filter(KPI.identifier != 'reflection')

但这会返回更多实际存在的Report个对象(我想每ReportKPI有一个KPI除了“反射”以外的任何对象。)

我想用SQLAlchemy实现的目标是什么?如果是这样,什么是神奇的词(请求似乎不起作用......)

1 个答案:

答案 0 :(得分:2)

EXISTS子查询表达式非常适合您的目标。编写此类查询的简便方法是:

Report.query.\
    filter(db.not_(Report.values.any(
        ReportKPI.kpi.has(identifier='reflection'))))

但这产生了2个嵌套的EXISTS表达式,尽管EXISTS中的连接也可以:

Report.query.\
    filter(db.not_(
        ReportKPI.query.
            filter_by(report_id=Report.id).
            join(KPI).
            filter_by(identifier='reflection').
            exists()))

最后,带有IS NULL的LEFT JOIN也是一个选项:

Report.query.\
    outerjoin(db.join(ReportKPI, KPI),
              db.and_(ReportKPI.report_id == Report.id,
                      KPI.identifier == 'reflection')).\
    filter(KPI.id.is_(None))