客体化关系:一对多,我能否有效地做到这一点?

我对Objectify很新,我有一个快速的问题,想要做最好的事情:

假设我有一个允许人们发送和接收消息的应用程序(为简单起见,请考虑发送电子邮件)。 当我的应用加载时,我不想从每个发送消息给给定用户的联系人加载每条消息。 那将是一种浪费。 相反,我想加载用户有消息的所有联系人(读取或未读取),以便我可以在我的应用程序上显示联系人列表,当用户点击给定联系人时我想加载所有来自该联系人的消息显示给用户。

如果不加载帐户的所有消息,我找不到这样做的好方法。 我在多对一关系中阅读了Objectify wiki,我仍然想不出一个不是非常低效的好方法。 这似乎是客观化网站推荐的方式,我必须为给定用户加载所有消息,然后解析它们以获得唯一的联系人。

我正在尝试使用尽可能少的App Engine读取和写入,并尽可能地尝试使用Smalls而不是Reads(运行我的应用程序的总体成本是我的一个大问题,而我正在制作这个) 。

在Objectify,我该怎么做?

这是从我对objectify-appengine google群组的回复中复制而来的: https ://groups.google.com/forum/?fromgroups#! topic / objectify-appengine / LlOyRJZRbnk

处理“聚合数据”时有三个主要选项,如您所描述的:

1)在需要时计算它

我认为你已经得出结论,这太贵了。

2)以批处理间隔计算并存储该结果

不太令人满意,因为它涉及延迟。 此外,您不希望每晚梳理整个数据库。

3)数据更改时更新聚合

这种方法每次数据更改时都会涉及更多工作,但几乎可以肯定您想要做的事情。

为每个用户创建某种联系人集合。 邮件到达时,请确保该收件人存在发件人联系人。 也许您还希望在收件人删除发件人的最后一封邮件时删除该联系人。

注意不要碰到实体组事务速率限制(每秒一次写入)。 我将引导您完成一些选择:

1)您可以在每个收件人中存储联系人列表:

class Person { @Id Long id; Set> contacts; } 

如果收件人一次收到20个新人的邮件,这将是一个明显的问题。 这几乎肯定是一个坏主意。 另一方面,查找联系人是谁的速度和速度都非常快。 一个小小的改进是将它移动到一个人的父母身份的单独实体中,这样你就不会总是加载这些数据:

 class Contacts { @Parent Key owner; @Id long id = 1; // there's only ever one of these per person, and it should have a predictable key for fetching Set> contacts; } 

当然,单个实体中的Set为您提供50,000个条目限制。 如果您首先达到1M实体大小限制,它可能会略小于此值。 如果你的钥匙大约是20个字符,它就会大致相同。 如果这是一个问题,你可以允许多个联系人实体,此时你有一些看起来像Brett Slatkin 2009年Google I / O谈话的关系索引实体模式: http : //www.youtube.com/watch?v = AgaL6NGpkB8

2)您可以在另一个方向存储联系人列表

 class Person { @Id Long id; @Index Set> contactOf; } 

这样可以找出您的联系人是多么昂贵 – 您需要一个仅限密钥的查询,而不是一个简单的按键。 但是你不再受实体写入率的限制了。 人们可能不会每秒发送多条消息,如果他们批量发送1000条消息,您可以在单个事务中更新contactOf。

如上所述,您可能希望将此索引移动到单独的实体中:

 class Contacts { @Parent Key person; @Id long id = 1; // there's only ever one of these per person, and it should have a predictable key for fetching Set> of; } 

3)您还可以将这些联系人存储在完全独立的实体中

 class Contact { @Parent Key person; @Id Long id; @Index Key owner; } 

这实际上只是一种解决方案#2的空间效率较低的方法。

重要的是在发送或接收每条消息时不断更新此结构。