为什么在过滤器中使用时,NDB属性需要包含在投影查询中?

时间:2013-10-18 12:29:57

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

我想知道为什么需要在投影查询中包含某些属性。我正在尝试获得一个独特的'foo'属性列表。

Object.query(projection=[Object.foo], distinct=True) \
    .filter(Object.username == user.nickname()) \
    .filter(Object.bar >= value) \
    .fetch()

这个给出了一个NeedIndexError,即使建议的索引已启动并正在运行。原因是基于bar> = value的第二个过滤器。通过删除该过滤器,查询工作完美,但无法实现目标。

Object.query(projection=[Object.foo, Object.bar], distinct=True) \
    .filter(Object.username == user.nickname()) \
    .filter(Object.bar >= value) \
    .fetch()

这个有效,但是现在你没有结果只有不同的foos,而是foo和bar的carthesian产品。这首先不是我们的目标。

Object.query() \
    .filter(Object.username == user.nickname()) \
    .filter(Object.bar >= value) \
    .fetch(projection=[Object.foo])

这个也有效,但没有办法按'foo'进行分组,从而产生一个带有重复'foo'值的列表。

如上所示,这个问题有解决方案,但两者都会产生更大的响应列表。如果可能的话,我想避免这种情况。因此,我有两个问题:

  1. 为什么filter()中的属性有时需要包含在投影中?这对我来说没有意义。另外,为什么这会导致NeedIndexError而不是更合适呢?
  2. 是否有任何解决方案没有上述缺点?或者我可能是从错误的一方面解决这个问题?欢迎任何建议。

1 个答案:

答案 0 :(得分:0)

这是索引推荐系统的一个错误,应该在App Engine的1.8.6版本中修复。问题是,为了提供不同的属性,这些属性必须首先在排序顺序中。请注意,不等式也必须在排序顺序中排在第一位。因此,如果您有不等式和不同的投影,则它们必须位于同一属性上。

投影必须在过滤器中的唯一原因是因为您要求不同的属性。您可以将此视为同一属性上的分组投影。要进行此分组,必须对属性进行排序以提供有效的重复数据删除。

执行所需查询的唯一方法是在内存中执行某些操作(正如您在问题中提到的那样)。另一种选择是没有不等式过滤器,然后在内存中进行过滤。

如果升级到1.8.6 SDK,则应该开始获得更好的(-ish)错误消息。