【问题标题】:How to design a thread style messaging system on Google App Engine如何在 Google App Engine 上设计线程式消息传递系统
【发布时间】:2011-08-26 16:00:07
【问题描述】:

我正在尝试使用 Django-nonrel 在 Google App Engine 上设计一个类似 gmail 的线程消息传递系统。我已经观看了“在 App Engine 上构建可扩展的复杂应用程序”并阅读了关于 SO 的以下问题。

App Engine Messaging System with Message Status - Design Pattern
database design in google app engine

我喜欢 Kevin 指出的想法 (App Engine Messaging System with Message Status - Design Pattern),所以我目前的模型是这样的:

class Message(models.Model):
    sender = models.ForeignKey(User)
    content = models.TextField()
    thread_id = models.IntegerField()

class MessageReceivers(models.Model):
    message = models.ForeignKey(Message)
    users = ListField(models.CharField())
    status = models.IntegerField()  # 1 unread, 2 read ....

Django-nonrel 上的 ListField 来自这里:
http://www.allbuttonspressed.com/blog/django/2010/03/Updates-on-djangoappengine

这是我的问题,我不知道如何实现在每个线程中显示消息计数,例如 gmail。让我澄清一下我的观点。
当用户小天狼星向哈利和罗恩发送消息时。模型(为解释而简化)应该是这样的:

Message
id = 1
sender = Sirius
thread_id = 1

MessageReceivers
message = 1
users = [Harry, Ron]

然后,哈利回复了小天狼星,但由于某种原因他没有包括罗恩:

Message
id = 2
sender = Harry
thread_id = 1

MessageReceivers
message = 2
users = [Sirius]

小天狼星也回复了哈利,但他又包括了罗恩:

Message
id = 3
sender = Sirius
thread_id = 1

MessageReceivers
message = 3
users = [Haary, Ron]

当小天狼星和哈利看到他们的收件箱时,会出现一个带有邮件计数的线程 (3)。并且 Ron 看到他的收件箱里有一个带有消息计数的线程 (2)。我应该如何计算这些数字?我应该制作一个新模型来保留它们吗?

提前致谢,

编辑
当 Kevin 向我介绍 Thread 模型时,我意识到我不需要关系索引模型来满足我的要求,所以我当前的模型如下所示。

class Message(models.Model):
    sender = models.ForeignKey(User)
    content = models.TextField()

class Thread(models.Model):
    user = models.ForeignKey(User)
    messages = ListField(models.CharField())    # array of message id
    lastmodified = models.DateTimeField()
    # could have a status field for read or unread, not sure for now

我可能会在这些模型的进一步开发中发现困难,但我会暂时使用它们:)

【问题讨论】:

  • 电子邮件(以及扩展名 gmail)不进行广播,因此不需要该演讲中描述的技巧。即使它确实以这种方式工作,普通电子邮件的收件人数量也足够少,几乎没有必要,对于邮件列表,listserv 完成了繁重的工作。您确定您的用例类似于 gmail 吗?
  • 是的,你是对的。我注意到我并不完全需要关系索引来满足我的要求,所以我决定使用 Kevin 解释的 Thread 模型。

标签: google-app-engine django-nonrel


【解决方案1】:

试试这个:

from collections import defaultdict

messages = MessageReceivers.objects.filter(users='Harry')

message_threads = []
for m in messages:
  message_threads.append(m.message.thread_id)

counted_threads = defaultdict(int)

for curr in message_threads:
    counted_threads[curr] += 1

这将为您提供 thread_id 的字典,以及它们的出现频率。

例如:

message_threads = ['a','b','c','a','a','b','a']

将产生

counted_threads == defaultdict(, {'a': 4, 'c': 1, 'b': 2})

【讨论】:

  • 附注解决您创建新模型的建议 - 如果您纯粹对给定用户的线程中消息的绝对数量感兴趣(因为它纯粹是附加的),但如果您希望能够分层,则可以作为另一种解决方案在消息状态过滤器中(即获取给定线程中给定用户的未读消息数),我推荐上述方法。
  • 感谢您的代码 Kevin。似乎您的代码也是一个很好的解决方案,但我还有一个问题。我实际上想要一个分页功能。假设每页有 20 个线程。所以我真正的 MessageReceiver 模型上有一个发送日期字段,查询应该看起来像 messages = MessageReceivers.objects.filter(users='Harry').order_by('-date')[:20] (我肯定会使用游标顺便说一句)但这并不是完全正确的 20 个线程,只有 20 条消息,它要么不能正确计算给定线程中的消息数量,因为同一线程中可能在 20 日和 21 日有消息
  • 我知道我可以通过进行一堆查询来实现它,但我看到很多时候人们对这样的解决方案说“这不是规模”,我很不自信。那么应该如何查询分页呢?
  • 似乎很难避免至少 2 个查询而不创建一个“线程”模型,该模型包含用户的消息键列表和“最后修改”字段。正如我所说,如果您不太关心“已读”、“未读”和“已归档”类型的状态,那么这很有效。
  • 哦,是的,我完全忘记了类型状态。但是“线程”模型听起来确实不错。好的,我会考虑的。非常感谢您的帮助。
【解决方案2】:

如果您的数字如此之低,我只会在客户端计算它们,而无需在服务器上进行统计。下载哈利的信息并计算它们。对 Sirius 做同样的事情。您每次都必须对它们进行计数(效率较低),但您不必存储或维护计数(效率更高),并且客户端的处理时间比服务器的便宜得多。

这似乎特别正确,因为这个数字只是一种方便。如果您想添加“按回复数量对对话进行排序”之类的功能,则需要将计数存储在服务器上,否则您并不真正关心这个数字。

【讨论】:

  • 感谢您的建议。好的,我喜欢您下载消息并在客户端上对它们进行计数的想法,因为我不需要按回复计数的排序功能。这个周末我会深入研究它。
猜你喜欢
  • 1970-01-01
  • 2016-07-01
  • 2021-10-12
  • 2023-03-27
  • 2011-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多