Нужно ли несколько таблиц ассоциации для этого отношения? - PullRequest
0 голосов
/ 09 января 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)
    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 ссылаются на одну и ту же запись в таблице ассоциации.

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

Спасибо!* Phil * 1019

Ответы [ 2 ]

2 голосов
/ 09 января 2012

Невозможно увидеть лес за деревьями. Это легко сделать с помощью аргумента 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")
1 голос
/ 09 января 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
...