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

Anu*_*yal 3 google-app-engine google-cloud-datastore

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

例如

class UnitPattern(db.Model):
    unit_pattern_set = db.ReferenceProperty(UnitPatternSet)
Run Code Online (Sandbox Code Playgroud)

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

例如

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()
Run Code Online (Sandbox Code Playgroud)

输出:

Total 5
ref set 2
ref not set 0
Run Code Online (Sandbox Code Playgroud)

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

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

Jam*_*ley 8

这在文档中简洁地描述:

索引仅包含具有索引引用的每个属性的实体.如果实体没有索引引用的属性,则实体将不会出现在索引中,并且永远不会是使用索引的查询的结果.

请注意,App Engine数据存储区分区分不具有属性的实体和拥有具有空值的属性的实体(无).如果希望某种实体成为查询的潜在结果,则可以使用为查询过滤器使用的属性分配默认值(如None)的数据模型.

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

丹·桑德森的书" 编程谷歌应用引擎"在第150页详细解释了这一点(遗憾的是,谷歌图书预览中未提供)

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

patterns = UnitPattern.all()
for pattern in patterns:
  if not pattern.unit_pattern_set:
    pattern.unit_pattern_set = None
    pattern.put()
Run Code Online (Sandbox Code Playgroud)

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