如何通过可以为空的重复字段来命令ndb查询

时间:2014-07-08 17:55:31

标签: python google-app-engine app-engine-ndb

我有一个带有重复属性的ndb模型:

class MyModel(ndb.Model):

  foo = ndb.KeyProperty(repeated=True)

我想在foo上执行不等式过滤器,这意味着我需要按foo排序:

query = MyModel.query()
query = query.filter(MyModel.foo != my_key)
# I don't actually care about doing this, but I have to because of the inequality filter.
query = query.order(MyModel.foo)

我希望查询包含foo为空的实体。如果我把一个虚拟字段放入foo中,它就可以工作:

def _pre_put_hook(self):
  if not self.foo:
    self.foo.append(ndb.Key('Dummy Kind', 'Dummy ID'))

但这似乎并不是一种干净的方法。还有更好的方法吗?

1 个答案:

答案 0 :(得分:4)

当数据存储区在其索引中存储repeated=True的属性时,它为stores one row for each value。这意味着如果您有一个空的重复属性,它将不会显示在您的EntitiesByProperty索引中。这意味着无法查询空的重复属性。

有几种选择,但每种选择都有自己的权衡:

添加虚拟值。

您建议的这种方法的好处是您现有的查询将为您提供所需的结果。但是,当您添加实际数据时,您必须处理清理虚拟密钥。

使用ComputedProperty

您可以为foo属性的大小添加新属性:

class MyModel(ndb.Model):
  foo = ndb.KeyProperty(repeated=True)
  foo_len = ndb.ComputedProperty(lambda self: len(self.foo))

但是,要获取foo值与my_key不匹配或为空的实体,您必须编写两个查询才能获得结果:

ndb.gql("SELECT * FROM MyModel WHERE foo != :1", my_key)
ndb.gql("SELECT * FROM MyModel WHERE foo_len == :1" 0)

请注意,如果foo没有重复,请使用以下查询获得所需结果:

ndb.gql("SELECT * FROM MyModel WHERE foo != :1", my_key)

即使没有空列表情况,在使用重复属性时也需要小心。特别是,只有一个重复的属性必须与您的密钥匹配。因此,自my_key2 != my_key以来,下面定义的模型仍会与您的查询匹配:

MyModel(foo=[my_key, my_key2])