App引擎数据存储:如何实现没有连接的帖子和标签?

时间:2009-07-03 13:33:23

标签: java google-app-engine database-design google-cloud-datastore

我正在使用Google App Engine(Java)构建一个应用程序,用户可以在其中发帖,我正在考虑为这些帖子添加标签,所以我会这样:

实体邮政中的

public List<Key> tags;

在实体标签中:

public List<Key> posts;

例如,查询具有特定标记的所有帖子会很容易,但我怎样才能获得包含标记列表的所有帖子? 我可以对每个标签进行查询,然后对结果进行交集,但也许有更好的方法......因为很多帖子都会很慢。

另一件可能更难的事情是有一个帖子,找到共同标签的帖子按照常用标签的数量排序,这样我就可以以某种方式获得“相似”帖子。

好吧,加入这会更容易,但是我开始使用app引擎,并且无法真正考虑更换连接的好方法。

谢谢!

3 个答案:

答案 0 :(得分:5)

使用这种设计,我担心您的标签实体可能成为瓶颈,特别是如果您希望某些标签非常常见。 我能想到的三个具体问题是获取和放置的效率,写入争用和爆炸式索引。让我们看一下stackoverflow的例子 - 现在有14,000个帖子被标记为“java”。

  1. 这意味着每次需要获取java标记实体时,您都会从数据存储中提取14k的关键数据。然后当你进行投注时,你会把它全部寄回去。这可能会增加很多字节。
  2. 除了来回的字节之外,每个put都需要更新索引。 ListProperty中的每个条目都映射到单独的索引条目。所以现在你正在进行大量的索引更新。这导致我们排名第3 ......
  3. 爆炸指数。每个实体都有一个限制,它可以有多少索引条目。我认为每个实体的限制是5000。所以这实际上是对有多少帖子可能具有相同标签的硬性限制。
  4. 进一步阅读:

    好消息是,只有Post实体可以轻松处理您的一些要求。 例如,您可以使用如下查询过滤器轻松找到包含 all 标记列表的所有帖子:

    Query q = pm.newQuery(Post.class)
    q.setFilter("tags" == 'Java' && "tags == 'appengine'");
    

    对于 java或appengine标记的所有帖子,您需要为每个标记执行一次查询,然后自己合并结果。数据存储区现在不处理OR / IN类型操作。

    查找相关帖子听起来很棘手。喝完咖啡后我会考虑一下。

答案 1 :(得分:1)

您可能希望查看Google IO中的视频。关系索引实体是您所需要的,允许您删除List<Key> posts实体上的Tag。以及List<Key> tags实体上的Post

答案 2 :(得分:1)

请参阅@ topchef的博文:Efficient Keyword Search with Relation Index Entities and Objectify for Google Datastore。它讨论了使用关系索引实体和Objectify实现列表属性的搜索。