客观化关系:一对多,我可以有效地做到这一点吗?

时间:2012-02-16 09:53:34

标签: java google-app-engine objectify

我对Objectify很新,我有一个简单的问题 做某事的最佳方式:

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

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

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

On Objectify,我该怎么做?

1 个答案:

答案 0 :(得分:11)

  

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

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

1)在需要时计算

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

2)以批次间隔计算并存储此结果

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

3)数据更改时更新聚合

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

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

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

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

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

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

class Contacts {
   @Parent Key<Person> owner;
   @Id long id = 1;   // there's only ever one of these per person, and it should have a predictable key for fetching
   Set<Key<Person>> 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<Key<Peson>> contactOf;
}

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

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

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

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

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

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

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