我有一个应用程序,其中有Course
,Topic
和Tag
。每个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循环遍历结果,仅选择Topic
的courseIds.contain(y)
。这将返回比我感兴趣的结果更多的结果,并且花费大量时间对这些结果进行反序列化,但是索引仍然很小。 select __KEY__ from Topic where tagIds = x
和select __KEY__ from Topic where courseIds = y
并在我的应用程序代码中找到交集。如果集合很小,这可能不是不合理的。 TopicTagLookup
和tagId
和courseId
字段。这些实体的父键将指向相关的Topic
。然后,我需要为CourseId x tagId x相关主题ID的每种组合制作一个TopicTagLookup
实体。这实际上就像创建我自己的索引一样。它仍然会爆炸,但是不会有5000个条目的限制。但是,现在,我需要将5000个实体写入同一实体组,这将超出实体组的写入速率限制! TopicTagQueryCache
实体将保存tagId
,courseId
和List<TopicId>
。然后查询看起来像select * from TopicTagQueryCache where tagId=x && courseId = y
,获取主题ID列表,然后在列表上使用getAllById
调用。与#3类似,但每个courseId x tagId只有一个实体。不需要实体组,但是现在我有了这个可能庞大的列表,可以进行事务维护。 Appengine似乎非常适合您可以预先计算的查询。我只是不太了解一种有效地预先计算此查询的方法。这个问题基本上可以归结为:
什么是组织数据的最佳方法,以便我们可以进行设置操作,例如在
Topic
和Course
的交点中找到Tag
? 最佳答案
您对选项的评估是正确的。不过,如果您不需要任何排序条件,那么App Engine数据存储区或多或少已经采用合并联接策略为您完成了选项3。您只需在选项1中详细说明即可进行查询,而无需任何类型或不等式过滤器,App Engine会在数据存储区内部进行合并联接,并仅返回相关结果。
选项4和5与this talk中记录的关系索引模式相似。
关于java - 使用Appengine避免爆炸式索引和实体组写入率限制,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5170591/