2011-08-26 84 views
1

我想通过使用Django-nonrel在Google App Engine上设计像线程消息传递系统这样的gmail。我看过“在App Engine上构建可扩展,复杂的应用程序”并阅读了关于SO的以下问题。如何在Google App Engine上设计线程风格的消息传递系统

App Engine Messaging System with Message Status - Design Pattern

我喜欢这个主意凯文指着(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 .... 

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

这里是我的问题,我不知道如何实现显示计数消息在每个线程像Gmail一样。让我澄清一下我的观点。
当一个用户Sirius向Harry和Ron发送消息时。 (简化的解释)模式应该是这样的:

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] 

和Sirius回复哈利太,但他又包括罗恩:

Message 
id = 3 
sender = Sirius 
thread_id = 1 

MessageReceivers 
message = 3 
users = [Haary, Ron] 

当天狼星和哈利看到自己的收件箱中,有一个与消息(3)的计数的线程。 Ron看到他的收件箱里有一条消息(2)。我应该如何计算这些数字?我应该制作一个新模型来保存它们吗?

由于提前,

编辑
正如凯文给我介绍了一个线程模型,我意识到,我不需要为我的要求的关系指数模型,所以我目前的模型看起来如下所示。

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 

我可能会发现,在进一步发展这些模型的困难,但我会和他们一起去暂且:)

+0

电子邮件(和扩展,Gmail)不做广播,因此不需要那个谈话中描述的技巧。即使它这样工作,普通电子邮件上的收件人数量也足够小,这几乎没有必要,而对于邮件列表,邮件列表的工作量也很大。你确定你的用例类似gmail吗? –

+0

是的,你是对的。我注意到我并不完全需要一个关系索引来满足我的需求,所以我决定像Kevin解释的那样使用Thread模型。 –

回答

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']

将产生

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

+0

p.s.为了解决您对创建新模型的建议 - 如果您纯粹对给定用户的线程中的消息绝对数量感兴趣(因为它纯粹是可加的),但是如果您希望能够将图层在消息状态的过滤器中(即获得给定用户在给定线程内未读消息的数量),我推荐上述方法。 –

+0

谢谢你的代码凯文。看起来你的代码也是一个很好的解决方案,但我还有一个问题。我其实希望有一个分页功能。假设每个页面上有20个线程。所以我真正的MessageReceiver模型有一个发送日期字段,查询应该看起来像'messages = MessageReceivers.objects.filter(users ='Harry')。order_by(' - date')[:20]'(我会肯定使用游标btw)但是,这并不完全正确的20个线程,只有20个消息,它或者不能正确计算给定线程内的一些消息,因为可能有消息在第20和第21个同一线程 –

+0

我知道我可以通过提出一系列的疑问来达到目的,但是我看到很多人对这样的解决方案说“这不是规模”,而且我也很不自信。那么我应该如何查询分页? –

1

如果你的数字会这么低,我只是指望他们客户端,并忘记在服务器上理货。下载Harry的消息并计算它们。对Sirius也一样。你必须每次计算它们(效率较低),但是不必存储或维护计数(更高效),并且客户端的处理时间比服务器的便宜。

这似乎特别真实,因为这个数字只是一种方便。如果您想要添加一项功能,例如“根据他们的回复数排序会话数”,您需要将计数存储在服务器上,但除此之外,您并不关心此数字。

+0

谢谢你的建议。好吧,我喜欢你的想法下载消息,并在客户端计数,因为我不需要通过回复计数的排序功能。我会在这个周末深入研究它。 –

相关问题