SQLAlchemy查询使用元素列表

时间:2017-06-08 13:01:52

标签: python sql sqlalchemy flask-sqlalchemy

我已经建立了一个大致如下的SQLAlchemy数据库:

class ChangelogEntry(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    apps = db.relationship('App', secondary=app_changelogEntry)
    appGroups = db.relationship('AppGroup', secondary=appGroup_changelogEntry)

class App(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32), unique=True, index=True)
    appGroups = db.relationship('AppGroup', secondary=app_appGroup)

class AppGroup(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32), unique=True, index=True)
    apps = db.relationship('App', secondary=app_appGroup)

更新:

app_changelogEntry = db.Table('App_ChangelogEntry',
    db.Column('app_id', db.Integer, db.ForeignKey('app.id')),
    db.Column('changelog_id', db.Integer, db.ForeignKey('changelog_entry.id'))
)

appGroup_changelogEntry = db.Table('AppGroup_ChangelogEntry',
    db.Column('appGroup_id', db.Integer, db.ForeignKey('app_group.id')),
    db.Column('changelogEntry_id', db.Integer, db.ForeignKey('changelog_entry.id'))
)

app_appGroup = db.Table('App_AppGroup',
    db.Column('app_id', db.Integer, db.ForeignKey('app.id')),
    db.Column('appGroup_id', db.Integer, db.ForeignKey('app_group.id'))
)

App可以是多个AppGroup的一部分,用户可以创建ChangelogEntries,并可以选择此ChangelogEntry所属的App / Apps和/或AppGroup。

看起来像这样:

enter image description here

好的。我只想获得属于例如所有的ChangelogEntries。 App3(App3是AppGroups Group1和Group2的一部分),在这种情况下是Group1和Group2。

我希望你可以帮助我!

1 个答案:

答案 0 :(得分:2)

联合可能是手头任务的良好匹配:找到具有直接应用关系和组的更改日志条目的联合。使用内部联接:

direct = db.session.query(ChangelogEntry).\
    join("apps").\
    filter(App.name == "App3")

groups = db.session.query(ChangelogEntry).\
    join("appGroups", "apps").\
    filter(App.name == "App3")

direct.union(groups).all()

由于组连接的多对多关系可能会为更改日志条目生成多行,但使用UNION而不是UNION ALL会解决这个问题。为了避免重复行开始,您可以使用semijoins / EXISTS:

direct = db.session.query(ChangelogEntry).\
    filter(ChangelogEntry.apps.any(App.name == "App3"))

groups = db.session.query(ChangelogEntry).\
    filter(ChangelogEntry.appGroups.any(
        AppGroup.apps.any(App.name == "App3")))

direct.union(groups).all()