我是一个入门的SQLAlchemy用户,对大量的文档感到沮丧。

我有一个新闻提要,当对某些内容对象创建了新的修订版时,该新闻提要会更新。 内容始终至少具有一个版本内容通过关联表与1个或多个主题相关。我给了一组 topic.id s T,并想显示属于内容中一行的N个最新的“已批准”修订版,该修订版在T中至少具有一个主题。(“已批准” ”只是修订版上的一个枚举属性)

以下是模型和相关属性:

class Revision(Model):
    __tablename__ = 'revision'

    class Statuses(object): # enum
        APPROVED = 'approved'
        PROPOSED = 'proposed'
        REJECTED = 'rejected'
        values = [APPROVED, PROPOSED, REJECTED]
    id = Column(Integer, primary_key=True)
    data = Column(JSONB, default=[], nullable=False)
    content_id = db.Column(db.Integer, db.ForeignKey('content.id'), nullable=False)

class Content(Model):
    __tablename__ = 'content'

    id = Column(Integer, primary_key=True)
    topic_edges = relationship(
        'TopicContentAssociation',
        primaryjoin='Content.id == TopicContentAssociation.content_id',
        backref='content',
        lazy='dynamic',
        cascade='all, delete-orphan'
    )

    revisions = relationship(
        'Revision',
        lazy='dynamic',
        backref='content',
        cascade='all, delete-orphan'
    )

class TopicContentAssociation(Model):
    __tablename__ = 'topic_content_association'
    topic_id = Column(Integer, ForeignKey('topic.id'), primary_key=True)
    content_id = Column(Integer, ForeignKey('content.id'), primary_key=True)

class Topic(Model):
    __tablename__ = 'topic'
    id = Column(Integer, primary_key=True)

到目前为止,这是我得到的:
revisions = session.query(Revision).outerjoin(Content).outerjoin(Topic).filter(
    ~exists().where(
        and_(
            Topic.id.in_(T),
            Revision.status == Revision.Statuses.APPROVED
        )           )
).order_by(Revision.ts_created.desc()).limit(N)

并发生此错误:

Select语句由于自相关而没有返回FROM子句;指定correlate()以手动控制关联。
SELECT *
FROM topic, revision
WHERE topic.id IN (:id_1, :id_2, :id_3...)
AND revision.status = :status_1

有趣的是,如果我删除了and_运算符和其中的第二个表达式(第3、5和6行),该错误似乎消失了。

奖励::)我也想只显示每行内容修订版。如果有人点击保存了很多次,我不希望订阅源困惑。

同样,我对SQLAlchemy(实际上是关系数据库)非常陌生,因此非常感谢初学者的答案!

编辑:在.correlate(Revision)子句修复问题后添加.where,但我仍在努力弄清楚这里到底发生了什么。

最佳答案

这是一个很晚的回复,但如果有人发现此主题,我要答复。

存在语句中的第二个表达式(Revision.status == Revision.Statuses.APPROVED)在查询中第二次调用表Revision。第一次调用此表是通过编写“session.query(Revision)”

如果我们在PostgreSQL中“翻译”您的exist语句,它将是:

EXISTS (SELECT 1
        FROM Revision
        WHERE topic.id IN (:id_1, :id_2, :id_3...)
        AND revision.status = :status_1
)

除非使用别名,否则不允许在同一查询中两次调用同一表(FROM修订版)。因此,您可以使用aliased()函数创建所需表的别名并解决您的问题。您的代码应该像这样:
from sqlalchemy.orm import aliased

aliasRev = aliased(Revision)

revisions = session.query(Revision).outerjoin(Content).outerjoin(Topic).filter(
    ~exists().where(
        and_(
            Topic.id.in_(T),
            aliasRev.status == Revision.Statuses.APPROVED
        )           )
).order_by(Revision.ts_created.desc()).limit(N)

关于由于自动相关,SQLAlchemy query.filter没有返回FROM子句,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35690518/

10-09 00:58