GAE中的ndb错误 - BadQueryError: 无法将FalseNode转换为谓词

14 投票
2 回答
3021 浏览
提问于 2025-04-17 19:47

我有一个在Google App Engine上运行的应用,使用的是Python语言。我的模型类是从ndb(google.appengine.ext.ndb)类扩展出来的。

我的一个视图会异步调用数据库,代码大概是这样的:

# ExerciseListLog is a ndb model class
# start_current, end_current are dates
# student_id is a string
# contents is a list of keys

exercise_log_query = ExerciseListLog.query(ndb.AND(ExerciseListLog.creation >= start_current,
    ExerciseListLog.creation < end_current,
    ExerciseListLog.user_id == student_id))
exercise_log_query = exercise_log_query.filter(ExerciseListLog.content.IN(contents))

future = exercise_log_query.count_async()

count = future.get_result() # this throws BadQueryError

但是在调用get_result()的时候出现了一个错误:BadQueryError: Cannot convert FalseNode to predicate。

这个错误只在我把代码部署到Google云上时出现,自己在本地运行是没问题的。

我对这个错误的意思完全不明白,查了很多资料也没找到有用的信息。有没有人知道这里面出了什么问题?

这是GAE日志中的完整错误堆栈信息:

Traceback (most recent call last):
  File "/base/data/home/apps/s~qmagtest/1.366092357976105290/zen/web/gae/convention.py", line 48, in make_convention
    method(*args, **kwargs)
  File "/base/data/home/apps/s~qmagtest/1.366092357976105290/core/web/qmhandler.py", line 48, in wrapper
    return method(self, *args, **kwargs)
  File "/base/data/home/apps/s~qmagtest/1.366092357976105290/core/user/login/security.py", line 36, in wrapper
    method(self, *args, **kwargs)
  File "/base/data/home/apps/s~qmagtest/1.366092357976105290/core/user/security.py", line 17, in wrapper
    method(self, *args_inner, **kwargs)
  File "/base/data/home/apps/s~qmagtest/1.366092357976105290/plugins/web/desempenho/estatisticas.py", line 127, in class_activities
    school_class.content)
  File "/base/data/home/apps/s~qmagtest/1.366092357976105290/plugins/web/desempenho/estatisticas.py", line 178, in _get_exercise_video_and_total_weekly_series
    exercise_log_count = exercise_count_futures[i].get_result()
  File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 325, in get_result
    self.check_success()
  File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 371, in _help_tasklet_along
    value = gen.send(val)
  File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 1227, in _count_async
    dsquery = self._get_query(conn)
  File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 873, in _get_query
    filters = filters._to_filter()
  File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 599, in _to_filter
    for node in self.__nodes
  File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 600, in <genexpr>
    if isinstance(node, PostFilterNode) == post))
  File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 425, in _to_filter
    'Cannot convert FalseNode to predicate')
BadQueryError: Cannot convert FalseNode to predicate

2 个回答

1

更新:

我发现如果我去掉这一行:

exercise_log_query = exercise_log_query.filter(ExerciseListLog.content.IN(contents))

那么程序就能正常运行了。

所以,这个错误和异步调用数据库没有关系。它发生的原因是因为Google AppEngine在每个查询中只支持一个不等式过滤器。

显然,使用“content.IN”被算作第二个不等式,这样是不被允许的。

那个错误信息可以更清楚一些。


更新:

结果证明Guido是对的,我之前的解释是错的。现在当contents不为空时,content.IN可以正常工作。

25

我觉得问题可能出在内容是一个空列表。这几乎是导致FalseNode出现的唯一原因。(另一个原因是调用AND()时没有传入参数。)你注意到去掉这一行后,正好支持了我的猜测。你可能没想到会发生这种情况,而在你本地测试时也从未出现过……你可能需要调试一下生成那个列表的代码。

我同意,错误信息可以更清晰一些。

撰写回答