Я пытаюсь создать социальную сеть, подобную сопоставлению «многие ко многим» в SQLAlchemy. То есть у меня есть класс Character и кросс-таблица character_relations для связи между Character и Character. До сих пор это легко:
character_relationships = Table('character_relationships', Base.metadata,
Column('me_id', Integer, ForeignKey('characters.id', ondelete=True, onupdate=True), nullable=False, primary_key=True),
Column('other_id', Integer, ForeignKey('characters.id', ondelete=True, onupdate=True), nullable=False, primary_key=True),
UniqueConstraint('me_id', 'other_id', name='uix_1')
)
class CharacterRelationship(object):
def __init__(self, me_id, other_id):
self.me_id = me_id
self.other_id = other_id
mapper(CharacterRelationship, character_relationships)
class Character(IdMixin, TimestampMixin, Base):
__tablename__ = "characters"
name = Column(Unicode, nullable=False)
friends = relationship(lambda: Character, secondary=character_relationships,
primaryjoin=lambda: Character.id==character_relationships.c.me_id,
secondaryjoin=lambda: Character.id==character_relationships.c.other_id,
backref=backref('knows_me')
)
Существует два возможных отношения: одностороннее и двустороннее. То есть в кросс-таблице я могу иметь
CharacterRelationship(me_id=1, other_id=2)
CharacterRelationship(me_id=2, other_id=1)
Аргумент Character.friends, приведенный выше, касается односторонних отношений. Как добавить свойство / column_property для двусторонних отношений?
То есть my_character.real_friends содержит только записи из CharacterRelationship, если отношение "стоит с обеих сторон".
Я знаю, что могу использовать что-то вроде
@property
def real_friends(self):
return set(my_character.friends) & set(my_character.knows_me)
но это не очень хорошо для sql, и я ожидаю, что это пересечение множеств на уровне базы данных будет очень быстрым. Но это еще не все!
Еще лучше иметь конечный объект, такой как:
character.friends.other_character
character.friends.relationship_type = -1 | 0 | 1
, где
- -1 означает, что я знаю других в одностороннем порядке,
- 0 двусторонний,
- 1 означает, что другие знают меня в одностороннем порядке
Видите ли вы какую-либо причину использовать эту логику на уровне базы данных? Если да, как бы вы это сделали?
Если знаете, знаете ли вы, как разместить простую двустороннюю часть real_friend на уровне базы данных?