5

我有很多(例如)贴有一个或多个标签的帖子。帖子可以创建或删除,用户也可以对一个或多个标签进行搜索请求(结合逻辑与)。我想到的第一个想法是一个简单的模型

class Post(db.Model):
  #blahblah
  tags = db.StringListProperty()

创建和删除操作的实现是显而易见的。搜索更复杂。要搜索 N 个标签,它将执行 N 个 GQL 查询,例如“SELECT * FROM Post WHERE tags = :1”,并使用游标合并结果,它的性能很差。

第二个想法是将不同实体中的标签分开

class Post(db.Model):
    #blahblah
    tags = db.ListProperty(db.Key) # For fast access

class Tag(db.Model):
    name = db.StringProperty(name="key")
    posts = db.ListProperty(db.Key) # List of posts that marked with tag

它从 db 中按键获取标签(比 GQL 快得多)并将其合并到内存中,我认为此实现比第一个实现具有更好的性能,但非常频繁地可用标签可能超过允许单个数据存储对象的最大大小. 还有另一个问题:数据存储区只能修改一个对象约 1/秒,因此对于经常使用的标签,我们也存在修改延迟的瓶颈。

有什么建议么?

4

2 回答 2

1

进一步尼克的提问。如果它是在他们查询中使用多个标签的逻辑 AND。使用 tags = tag1 AND tags = tag2 ... 在单个查询中设置成员资格是数据存储区的亮点之一。您可以在一个查询中获得结果。

http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html#Properties_With_Multiple_Values

于 2010-11-29T05:26:56.630 回答
0

可能的解决方案是采用第二个示例,并以允许对更大集合进行有效查询的方式对其进行修改。想到的一种方法是将多个数据库实体用于单个标签,并以您很少需要获得多个组的方式对它们进行分组。如果默认排序顺序(好吧,我们只称其为唯一允许的)是按日期排序,则按该顺序填充标签组实体。

class Tag(db.Model):
    name = db.StringProperty(name="key")
    posts = db.ListProperty(db.Key) # List of posts that marked with tag
    firstpost = db.DateTimeProperty()

在组中添加或删除标签时,请检查该组中有多少帖子,如果您添加的帖子会使帖子超过 100 个帖子,请将其分成两个标签组。如果您要删除帖子以使该组的帖子少于 50 个,请从上一个或下一个组中窃取一些帖子。如果相邻组之一也有 50 个帖子,只需将它们合并在一起。按标签列出帖子时(按发布日期顺序),您只需要获得少数组。

这并不能真正解决高需求标签问题。

考虑一下,插入更投机一点可能是可以的。获取最新的标签组条目,合并它们并放置一个新的标签组。交易的滞后实际上可能不是一个真正的问题。

于 2010-11-25T20:10:48.537 回答