0
0 комментариев

Есть две таблицы — таблица (музыкальных) инструментов и таблица нот. Они соотносятся как many to many. Связующая таблица — instrument_sheet.

Пример:

Sheet(id=1, name='Произведение 1')
Sheet(id=2, name='Произведение 2')
Instrument(id=1, name='скрипка')
Instrument(id=2, name='виолончель')
Instrument(id=3, name='фортепиано')
instrument_sheet(sheet_id=1, instrument_id=1)
instrument_sheet(sheet_id=1, instrument_id=2)
instrument_sheet(sheet_id=2, instrument_id=2)
instrument_sheet(sheet_id=2, instrument_id=3)

В итоге — в нотах первого произведения участвуют скрипка и виолончель, а второго — виолончель и фортепиано.

instrument_sheet_association = db.Table('instrument_sheet',
    db.Column('instrument_id', db.Integer, db.ForeignKey('instrument.id')),
    db.Column('sheet_id', db.Integer, db.ForeignKey('sheet.id'))
    )
 
class Instrument(db.Model):
u'''
Инструменты
'''
    id = db.Column(db.Integer, primary_key = True)
    name = db.Column(db.String(120), index = True)
 
class Sheet(db.Model):
u'''
Произведения
'''
    id = db.Column(db.Integer, primary_key = True)
    name = db.Column(db.String(120), index = True)
    instruments = db.relationship('Instrument',
        secondary=instrument_sheet_association,
        backref=db.backref('sheets', lazy='dynamic'))

Необходимо найти все ноты, у которых определенный набор инструментов.

Пока планирую обработать запрос питоном:

instrument_names = ['скрипка', 'виолончель']
sheets = Sheet.query.join(Sheet.instruments).filter(\
    Instrument.name.in_(instrument_names)).all()
filtered_sheets = []
instrument_set = set(instrument_names)
for sheet in sheets:
    instruments = set([instrument.name\
        for instrument in sheet.instruments])
    if instruments == instrument_set:
        filtered_sheets.append(sheet)
return filtered_sheets

Подскажите, как правильно стоит решать такую проблему?

Обновление

orietdb написан на java. Не хочется тащить яву в проект. Плюс задача довольно обыденная. Самый, наверное, избитый пример — это пользователи и роли. У каждого пользователя может быть несколько ролей. Требуется найти всех пользователей с ролями = ‘менеджер’ и ‘редактор’ например. Думаю, что для этой задачи мне поможет оператор having. Осталось это только попробовать и переписать на sqlalchemy. Как будет время, я это сделаю и выложу сюда результат.


Добавить комментарий