分页和多个关系实体索引与AppEngine
这是一个关于与包含多个实体索引的模型分页的常见问题。举一个例子,这很容易,所以让我们考虑Brett Slatkin在其视频中提供的示例(http://www.google.com/events/io/2009/sessions/BuildingScalableComplexApps.html)。分页和多个关系实体索引与AppEngine
你有你的消息模型(我忽略了MessageIndex模型),并且我还添加了两个额外的属性(用于发布和到期时间)。
class Message(db.Model):
sender = db.StringProperty()
body = db.TextProperty()
published = db.DateTimeProperty()
expires = db.DateTimeProperty()
现在我有兴趣在多个领域做过滤,比如发表在一个特定的时间窗口消息。例如
select * from Message where pubished > some_date and expires < some_other_date
由于GAE不允许在多个领域的不平等过滤器,我们必须将模型分解成额外的索引。所以,现在我们已经为发布和到期字段的索引,给我们以下车型(含消息实例是MessagePublishedIndex和MessageExpiryIndex实例的父):
class Message(db.Model):
sender = db.StringProperty()
body = db.TextProperty()
class MessagePublishedIndex(db.Model):
published = db.DateTimeProperty()
class MessageExpiryIndex(db.Model):
expires = db.DateTimeProperty()
及以下key_only查询:
publish_keys = MessagePublishedIndex.all(key_only = True).filter("published >", some_date)
expire_keys = MessageExpiryIndex.all(key_only = True).filter("expires <", some_other_date)
msgs_by_pubdate = db.get([k.parent() for k in publish_keys])
msgs_by_expiry = db.get([k.parent() for k in expire_keys])
现在,Il必须完成这些列表的交集才能找到常见的列表,以获取特定时间窗口内的所有消息。
这看起来很浪费。有没有更简单的方法来做到这一点?此外,如果索引中的字段是ListProperty,则此问题会加剧,因为key_only查询不能具有“IN”过滤器。更糟糕的是,如果我想分页(即“计数”结果来自“偏移量”),则必须手动丢弃第一个“偏移”结果,然后进行相交。当然必须有一个更简单(更聪明)的方式来做到这一点。有任何想法吗?它足够糟糕GAE不允许在多个字段上使用不等式过滤器(尽管出于效率的原因),但是必须手动完成所有的Zig-zags效率似乎相当低效(更不要说运行cpu和时间限制)。
在你的情况,我会创建一个单一的关系指数实体
class MessageIndex(db.Model):
keywords = db.StringListProperty();
其中的关键字列表中每个项目将在格式<属性> = <值>
如:关键词= [“published = 2011-03-24”,“expires = 2011-03-25”]
您需要自己做序列化/反序列化来获取属性值。或者,您仍然可以将属性值存储在消息模型中,仅用于冗余。但是,该方法不适用于范围查询。 (我还没有测试,但你可能可以使用带前缀的查询来伪造范围查询:u“published = 2010”+ u“\ ufffd”,here is more details)
对GAE进行优化始终是一项挑战。但它很有趣,也很有收获。
我不完全理解这个问题。也许代码示例混淆了? – max 2010-10-24 16:16:59
对不起。我的帖子不知何故被切断了,所以我重新输入了丢失的位。 – Sri 2010-10-25 00:03:22