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'))
)
Приложение может входить в состав нескольких групп приложений, а пользователи могут создавать ChangelogEntries и могут выбирать, к каким приложениям / приложениям и / или группам приложений принадлежит эта ChangelogEntry.
Это выглядит так:
Хорошо. Я просто хочу получить все ChangelogEntries, которые принадлежат, например, App3 (App3 является частью AppGroups Group1 и Group2) и в этом случае Group1 и Group2.
Я надеюсь, что вы можете помочь мне с этим!
1 ответ
Объединение может хорошо соответствовать поставленной задаче: найти объединение записей журнала изменений с прямыми отношениями приложения и через группы. Использование внутренних объединений:
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()