我有一个应用程序,其中有CourseTopicTag。每个Topic可以在许多Course中,也可以在许多Tag中。我想查找具有特定Topic x且位于特定Tag y中的每个Course

  • 天真地,我给每个标准一个Course id和Tag id的列表,所以我可以select * from Topic where tagIds = x && courseIds = y。我认为此查询需要一个爆炸式的索引:具有30个 class 和30个标签的我们正在查看〜900个索引条目,对吗?在50 x 20的分辨率下,我远远超过了5000个条目的限制。
  • 我可以只使用select * from Topic where tagIds = x,然后使用for循环遍历结果,仅选择TopiccourseIds.contain(y)。这将返回比我感兴趣的结果更多的结果,并且花费大量时间对这些结果进行反序列化,但是索引仍然很小。
  • 我可以select __KEY__ from Topic where tagIds = xselect __KEY__ from Topic where courseIds = y并在我的应用程序代码中找到交集。如果集合很小,这可能不是不合理的。
  • 我可以创建一种联接表,TopicTagLookuptagIdcourseId字段。这些实体的父键将指向相关的Topic。然后,我需要为CourseId x tagId x相关主题ID的每种组合制作一个TopicTagLookup实体。这实际上就像创建我自己的索引一样。它仍然会爆炸,但是不会有5000个条目的限制。但是,现在,我需要将5000个实体写入同一实体组,这将超出实体组的写入速率限制!
  • 我可以预先计算每个查询。 TopicTagQueryCache实体将保存tagIdcourseIdList<TopicId>。然后查询看起来像select * from TopicTagQueryCache where tagId=x && courseId = y,获取主题ID列表,然后在列表上使用getAllById调用。与#3类似,但每个courseId x tagId只有一个实体。不需要实体组,但是现在我有了这个可能庞大的列表,可以进行事务维护。

  • Appengine似乎非常适合您可以预先计算的查询。我只是不太了解一种有效地预先计算此查询的方法。这个问题基本上可以归结为:

    什么是组织数据的最佳方法,以便我们可以进行设置操作,例如在TopicCourse的交点中找到Tag

    最佳答案

    您对选项的评估是正确的。不过,如果您不需要任何排序条件,那么App Engine数据存储区或多或少已经采用合并联接策略为您完成了选项3。您只需在选项1中详细说明即可进行查询,而无需任何类型或不等式过滤器,App Engine会在数据存储区内部进行合并联接,并仅返回相关结果。

    选项4和5与this talk中记录的关系索引模式相似。

    关于java - 使用Appengine避免爆炸式索引和实体组写入率限制,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5170591/

    10-13 04:15