Нужно ли мне несколько ассоциативных таблиц для этой связи?

Я пытаюсь понять, как лучше всего построить отношения, которые сопоставляют множество констант со многими элементами.

Мои первоначальные отношения, у Предмета есть Константа, выглядели так.

class Constant(Base):
    __tablename__ = "Constant"
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(64), nullable=False)

class Item(Base):
    __tablename__ = "Item"
    id = Column(Integer, primary_key=True, autoincrement=True)
    constantId = Column(Integer, ForeignKey("Constant.id"))
    constant = relationship("Constant")

Однако мне действительно нужно, чтобы мой элемент имел более одной константы, что-то вроде этого...

class Item(Base):
    __tablename__ = "Item"
    id = Column(Integer, primary_key=True, autoincrement=True)
    constant1Id = Column(Integer, ForeignKey("Constant.id"))
    constant1 = relationship("Constant")
    constant2Id = Column(Integer, ForeignKey("Constant.id"))
    constant2 = relationship("Constant")

Моей первой попыткой было использовать таблицу ассоциаций...

item_to_constant_assoc = Table("itemToConstantAssoc", Base.metadata, Column("constantId", Integer, ForeignKey("Constant.id"), Column("itemId", Integer, ForeignKey("Item.id")))

при обновлении класса Item соответственно:

Class Item(Base):
__tablename__ = "Item"
id = Column(Integer, primary_key=True, autoincrement=True)
constant1 = relationship("Constant", secondary=item_to_constant_assoc, uselist=False)
constant2 = relationship("Constant", secondary=item_to_constant_assoc, uselist=False)

Это не удалось (понятно, если посмотреть на созданные таблицы MySQL), потому что Item.constant1 и Item.constant2 ссылались на одну и ту же запись в таблице ассоциаций.

Мой следующий шаг — добавить еще одну ассоциативную таблицу для второй константы, но я должен задаться вопросом, не ошибаюсь ли я, поскольку я, кажется, создаю большое количество таблиц для относительно простого сопоставления. Я прочитал документацию. Он подробный и содержательный (спасибо Майклу Байеру!), и я мог просто пропустить какой-то раздел. Может ли кто-нибудь дать мне несколько указателей на эту проблему или на то, что я должен искать в документах?

Спасибо! Фил


person Phil Boltt    schedule 09.01.2012    source источник
comment
Описание вашей проблемы излишне абстрактно. Пожалуйста, объясните проблему, которую вы пытаетесь решить, более четко, чтобы мы могли дать содержательный ответ.   -  person SingleNegationElimination    schedule 09.01.2012
comment
@TokenMacGuy Это, вероятно, менее абстрактно по отношению к реальной проблеме, которую я пытаюсь решить, чем вы думаете. У меня есть таблица констант в области редактирования видео (например, константа с именем FPS23976 определяет частоту кадров 23,976 кадра в секунду). Таблица Item определяет записывающее устройство. У него есть как скорость захвата, так и скорость воспроизведения, обе из которых я хотел бы сослаться на таблицу констант. Извините, если неправильно сформулировал проблему. Это не моя область знаний. Мой вопрос сводится к следующему: является ли несколько ассоциативных таблиц лучшим способом построения этих отношений?   -  person Phil Boltt    schedule 09.01.2012
comment
@PhilBoltt: пожалуйста, разместите разъяснение как обновление к вопросу. Не комментарий. Но первоклассное обновление, так что вопрос один, интегрированное целое. Не куча рассматриваемых идей плюс комментарии.   -  person S.Lott    schedule 09.01.2012
comment
Камеры и частота кадров довольно конкретны, гораздо более конкретны, чем предметы и константы!   -  person SingleNegationElimination    schedule 09.01.2012
comment
@TokenMacGuy Точка принята. Спасибо за ваш вклад.   -  person Phil Boltt    schedule 09.01.2012


Ответы (2)


Не видел леса за деревьями. Это легко сделать, используя аргумент primaryjoin отношения.

class Item(Base):
    __tablename__ = "Item"
    id = Column(Integer, primary_key=True, autoincrement=True)
    constant1Id = Column(Integer, ForeignKey("Constant.id"))
    constant1 = relationship("Constant", primaryjoin="Constant.id==Item.constant1Id")
    constant2Id = Column(Integer, ForeignKey("Constant.id"))
    constant2 = relationship("Constant", primaryjoin="Constant.id==Item.constant2Id")
person Phil Boltt    schedule 09.01.2012

Ассоциация «многие ко многим» уже позволяет каждому элементу иметь неограниченное количество констант. Вам не нужно ничего, кроме этих двух базовых таблиц.

class Constant(Base):
    __tablename__ = "Constant"
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(64), nullable=False)

class Item(Base):
    __tablename__ = "Item"
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(64), nullable=False)    

item_to_constant_assoc = Table("itemToConstantAssoc", Base.metadata, Column("constantId", Integer, ForeignKey("Constant.id"), Column("itemId", Integer, ForeignKey("Item.id")))

На данный момент каждый элемент имеет неограниченное количество констант. Если вам нужна конкретная константа, вы должны запросить константу по атрибуту имени в таблице констант. Ваша таблица ассоциаций — это просто список пар ключей: (itemID, ConstantId).

Набор всех констант для элемента представляет собой объединение трех таблиц для всех строк ассоциации, соединенных с соответствующими строками констант для данного элемента.

Набор всех элементов для константы представляет собой соединение из трех таблиц для всех строк ассоциации, которые соединяются с соответствующими строками элементов для данной константы.

Конкретная константа для элемента должна быть получена через соединение. Вы думаете об этом как о наборе всех Констант для данного Элемента, где даны как Элемент, так и имя Константы. SQL включает соединение, даже если извлекается только одна строка.

Я думаю, что ваш общий запрос на связывание константы со всеми соответствующими элементами или элемента со всеми соответствующими константами будет выглядеть примерно так.

  query(Item). join(item_to_constant_assoc.itemId==Item.itemId). join(item_to_constant_assoc.contantId==Constant.constantId
person S.Lott    schedule 09.01.2012
comment
Спасибо, Стивен. Это делает роль таблицы ассоциаций более ясной для меня. - person Phil Boltt; 09.01.2012