Java 在低级数据存储api中处理一对多关系的最佳方法是什么?

Java 在低级数据存储api中处理一对多关系的最佳方法是什么?,java,google-app-engine,google-cloud-datastore,Java,Google App Engine,Google Cloud Datastore,我已经在Java中使用AppEngine的低级数据存储API有一段时间了,我正在尝试找出处理一对多关系的最佳方法。想象一下一对多的关系,比如“任何一个学生都可以拥有零台或多台计算机,但每台计算机都只有一个学生拥有” 这两种选择是: 让学生实体存储与学生关联的计算机的密钥列表 让计算机实体存储拥有计算机的学生的单个密钥 我觉得第二种选择更好,但我很好奇其他人怎么想 选项一的优点是,您可以在不使用查询的情况下获取所有“many”。可以使用get()并传入存储的键列表,向数据存储请求所有实体。这种

我已经在Java中使用AppEngine的低级数据存储API有一段时间了,我正在尝试找出处理一对多关系的最佳方法。想象一下一对多的关系,比如“任何一个学生都可以拥有零台或多台计算机,但每台计算机都只有一个学生拥有”

这两种选择是:

  • 让学生实体存储与学生关联的计算机的密钥列表
  • 让计算机实体存储拥有计算机的学生的单个密钥
我觉得第二种选择更好,但我很好奇其他人怎么想

选项一的优点是,您可以在不使用查询的情况下获取所有“many”。可以使用get()并传入存储的键列表,向数据存储请求所有实体。这种方法的问题是不能让数据存储对从get()返回的值进行任何排序。你必须自己分类。另外,您必须管理一个列表,而不是单个键

选项二看起来不错,因为没有需要维护的列表。此外,您还可以按计算机的属性排序,只要它们是该属性的索引。想象一下,尝试为一名学生获取所有计算机,结果按购买日期排序。使用方法二,它是一个简单的查询,在我们的代码中不进行排序(数据存储的索引负责)


排序其实并不难,但比使用排序索引(~O(n)遍历索引)要花费更多的时间(~O(n)用于排序)。折衷是处理时间的索引(数据存储中的空间)。正如我所说,我的直觉告诉我,选项二是一个更好的通用解决方案,因为它让开发人员在恢复结果的顺序方面有更多的灵活性,而代价是额外的索引(谷歌的定价模式非常便宜)。有人同意、不同意或有意见吗

你考虑过两者都做吗?然后,您可以通过键快速获取学生拥有的计算机列表,或者使用查询以某种排序顺序返回结果。我不认为在学生模型上维护一个密钥列表像你想象的那样可怕


不要低估通过键直接获取实体的好处。根据,这可能比查询快4-5倍。

您考虑过两者都做吗?然后,您可以通过键快速获取学生拥有的计算机列表,或者使用查询以某种排序顺序返回结果。我不认为在学生模型上维护一个密钥列表像你想象的那样可怕


不要低估通过键直接获取实体的好处。根据,这可能比查询快4-5倍。

这两种方法在不同的情况下都是有效的,尽管选项二——在“多”端存储单个引用——是更常见的方法。您使用哪种方法取决于您需要如何访问数据。

这两种方法在不同的情况下都是有效的,尽管选项二(在“多”端存储单个引用)是更常见的方法。您使用哪一种取决于您需要如何访问数据。

您可能有第三种选择,即为用户将所有计算机存储在记录中。不过我不熟悉你提到的数据存储。在用户记录中存储计算机对于GAE的数据存储可能不会太好。这将有点棘手(在计算机模型中,每个字段可能需要一个
ListProperty
,而这些都不能被索引,否则会出现索引爆炸的问题)。如果您不需要搜索计算机,并且您不介意在检索学生实体时总是检索所有学生计算机信息的开销,那么这可能没问题。您可能有第三个选项,即为用户将所有计算机存储在记录中。不过我不熟悉你提到的数据存储。在用户记录中存储计算机对于GAE的数据存储可能不会太好。这将有点棘手(在计算机模型中,每个字段可能需要一个
ListProperty
,而这些都不能被索引,否则会出现索引爆炸的问题)。如果您不需要搜索计算机,也不介意在检索学生实体时总是检索所有学生计算机信息的开销,那么这可能没问题。“不要低估通过键直接获取实体的好处。根据本文,这可能比查询快4-5倍。”本文在提到这个数字时引用了系统状态页()。但这不是有点不公平吗。我认为GET通常用于返回单个条目,而查询通常会返回更多数据,有时甚至更多。“不要低估通过键直接获取实体的好处。根据本文,这可能比查询快4-5倍。”本文引用了系统状态页()当它提到这个数字时。但这不是有点不公平吗。我认为GET通常用于返回单个条目,而查询通常会返回更多数据,有时甚至更多。