如何在Google应用引擎数据库中过滤带有空引用的行

时间:2010-01-07 11:01:29

标签: google-app-engine google-cloud-datastore

我有一个Model UnitPattern,它引用另一个Model UnitPatternSet

e.g。

class UnitPattern(db.Model):
    unit_pattern_set = db.ReferenceProperty(UnitPatternSet)

在我的视图中我想显示所有UnitPatterns,其unit_pattern_set引用为None,但查询UnitPattern.all()。filter(“unit_pattern_set =”,None)什么都不返回,虽然我总共有5个UnitPatterns,其中2个有'unit_pattern_set'设置,3没有

e.g。

print 'Total',UnitPattern.all().count()
print 'ref set',UnitPattern.all().filter("unit_pattern_set !=", None).count()
print 'ref not set',UnitPattern.all().filter("unit_pattern_set =", None).count()

输出:

Total 5
ref set 2
ref not set 0

查询2和3的总和不应该等于查询1吗?

原因似乎是我之后添加了引用属性unit_pattern_set,并且之前存在这些UnitPattern对象,但是我如何过滤这些实体呢?

1 个答案:

答案 0 :(得分:8)

这在docs

中简明扼要地描述
  

索引仅包含实体   拥有所提到的每一处财产   指数。如果实体没有   财产所指的财产,指数   实体不会出现在索引中,   永远不会是结果   使用索引的查询。

     

请注意   App Engine数据存储区制作了一个   区分一个实体   不拥有财产和财产   拥有该财产的实体   空值(无)。如果你想   每个实体都是一个   查询的潜在结果,你可以   使用分配的数据模型   默认值(如无)到   查询过滤器使用的属性。

在您的情况下,您有3个实体根本没有设置unit_pattern_set属性(因为该属性在创建这些实体时未在模型中定义) - 因此这些属性不会不存在于该实体的数据库表示中,因此该实体不会出现在该类实体的该属性的索引中。

丹·桑德森的书Programming Google App Engine在第150页详细解释了这一点(遗憾的是,谷歌图书预览中未提供)

要修复已有的模型,你必须迭代UnitPattern上的查询(我没有测试过以下代码,请在运行实时数据之前检查它):

patterns = UnitPattern.all()
for pattern in patterns:
  if not pattern.unit_pattern_set:
    pattern.unit_pattern_set = None
    pattern.put()

编辑:此外,Updating you model's schema文章讨论了可用于处理架构更改的策略,例如将来。但是,该文章相当陈旧,其方法需要Web浏览器继续按下url以触发下一个作业来更新更多记录 - 现在Task Queues存在,您可以使用一系列任务来进行更改。 article on using deferred.defer有一个你可以利用的框架 - 它完成了少量的工作,捕获了DeadlineExceededError,并使用处理程序对一个新任务进行排队,这个任务将在当前任务停止的地方进行排队。