App Engine中的简单消息传递模型

时间:2011-11-28 20:21:22

标签: google-app-engine

我正在开发一个非常简单的类似电子邮件的消息传递功能,作为App Engine应用程序的一部分。它比电子邮件更简单,因为没有“主题行”。换句话说,两个用户(或更多,但不是数百个)可以在对话线程中交换消息,该对话线程包含所有来回消息(如IM,但会话之间存在持续的线程)。到目前为止,我正在考虑使用两种类型的实体对其进行建模:消息和对话

class Message(db.Model):
    sender = StringProperty(required=True)
    receiver = StringProperty(required=True)
    message = TextProperty(required=True)
    timestamp = DateTimeProperty(auto_now_add=True)

class Conversation(db.Model):
    messages = ListProperty(int) # List holding the datastore-assigned integer ids of the messages in this conversation
    users = StringListProperty()

由于创建Message需要创建或修改Conversation,我希望将Message和Conversation存储在同一个实体组中,以便这些更改可以在事务中发生。我想我会将Message实体作为其关联的Conversation实体的子节点。

Message需要Conversation实体的密钥才能将其指定为父级。 Conversation需要Message的id将它存储在messages属性中。

最有效的方法是什么?

  • 如果我让数据存储区为Conversation实体分配了一个id,那么我需要(1)将Conversation实体放入数据存储区以获取其id,(2)将Message实体放入数据存储区以获取其id, (3)更新Conversation实体以添加新的消息ID并将其重新放入数据存储区。这需要3次访问数据存储区,这看起来效率低下。
  • 我还可以为Conversation实体创建一个唯一的密钥名称(例如,';'。join(sorted(conv.users))。通过这样做,我可以避免三次访问上面概述的数据存储区之一。

有没有办法通过一次访问数据存储区来完成此操作?我担心边际效率,我真的不担心吗?对于我想要做的事情,是否有更智能的设计模式?如果是这样,我真的很感激指针。

1 个答案:

答案 0 :(得分:4)

您正在颠覆传统的设计模式,即:

class Conversation(db.Model):
    users = StringListProperty()

class Message(db.Model):
    sender = StringProperty(required=True)
    receiver = StringProperty(required=True)
    message = TextProperty(required=True)
    timestamp = DateTimeProperty(auto_now_add=True)
    conversation = db.ReferenceProperty(Conversation)

在上面的模型中,除非您要更新用户列表,否则在存储新邮件时不需要修改对话实体。我建议使用此项,除非有理由不这样做。

这也应该更具可扩展性。如果您的对话达到1000条消息,则您不必在单个对话实体上存储1000条消息ID属性。

但是,我们假设您要保留原始模型。要在一次旅行中存储对话和消息,您需要急切地分配消息ID。我的建议是生成一个UUID(例如,使用uuid.uuid4())并将其指定为消息密钥名称(并将其附加到消息列表),而不是等待数据存储区分配ID。