我有很多(例如)帖子,标有一个或多个标签。可以创建或删除帖子,并且用户也可以对一个或多个标签进行搜索请求(与逻辑AND结合)。 我想到的第一个想法是一个简单的模型
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 /秒,因此对于频繁使用的标记,我们也存在修改延迟的瓶颈。
有什么建议吗?
答案 0 :(得分:1)
进一步提问尼克的提问。如果是逻辑AND,则在查询中使用多个标签。使用tags = tag1 AND tags = tag2 ...在单个查询中设置成员资格是数据存储区的闪亮功能之一。您可以在一次查询中获得结果。
答案 1 :(得分: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个帖子,则将它们合并在一起。按标签列出帖子(按照日期后的顺序),您只需要获得少数几个组。
这并不能真正解决高需求标签问题。
考虑到这一点,插入可能更具推测性。获取最新的标记组条目,合并它们并放置一个新的标记组。事务中的滞后实际上可能不是一个真正的问题。