确保 SqlAlchemy 中多对多映射实体的唯一组合

问题描述 投票:0回答:1

我有以下带有关联表的 SqlAlchemy 模型。它们代表聊天对话。每个聊天可以有 0 - N 个用户参与:

class Chat(BaseDbModel):
    __tablename__ = "chats"

    id = Column(Integer, primary_key=True)        
    users = relationship("User", secondary=chat_user_association, back_populates="chats")
    ...

class User(BaseDbModel):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True)
    chats = relationship("Chat", secondary=chat_user_association, back_populates="users")
    ... 

chat_user_association = Table(
    'chat_user',
    BaseDbModel.metadata,
    Column('chat_id', Integer, ForeignKey('chats.id')),
    Column('user_id', Integer, ForeignKey('users.id')),
)

没有什么可以阻止我使用同一组用户 ID 创建多个聊天。我想防止这种行为发生,最好是在数据库级别。

预期行为示例:

我希望能够使用用户 ID {1, 2}、{1, 2, 3}、{2, 3} 创建聊天,但它不应该能够使用用户 ID {2 创建另一个聊天, 1, 3} 因为这会导致口是心非。

最干净的解决方案/方法是什么?我可以在创建聊天对象时进行手动检查,但我更喜欢一种更能证明竞争条件的方法。我使用 PostgreSQL。

python postgresql sqlalchemy
1个回答
0
投票

一个简单的解决方案可能是对用户 ID 进行排序,使其顺序具有确定性,并使用它们创建唯一标识符。将其与聊天 ID 一起存储在所需的唯一列中。像这样的东西:

# Creating strings like "1-2", "1-2-3":
user_ids_key = '-'.join([str(user_id) for user_id in sorted(chatting_user_ids)])

然后在表格中添加一列,例如:

class Chat(BaseDbModel):
    __tablename__ = "chats"

    id = Column(Integer, primary_key=True) 
    user_ids_key = Column(String, unique=True, nullable=False)
    #...

限制我想这样做的一个缺点是,如果你在每个聊天中都有很多用户,或者你的 ID 非常大,那么这可能会崩溃,但它应该是一个可靠的解决方案,直到这成为一个问题。

© www.soinside.com 2019 - 2024. All rights reserved.