我需要在NDB queries上获取与给定的开始和结束日期匹配的对象,但由于NDB抱怨,我无法执行传统的简单查询:
from google.appengine.ext import ndb
from datetime import datetime
from server.page.models import Post
now = datetime.now()
query = Post.query(
Post.status == Post.STATUS_ACTIVE,
Post.date_published_start <= now,
Post.date_published_end >= now,
)
count = query.count()
错误:
BadRequestError: Only one inequality filter per query is supported.
Encountered both date_published_start and date_published_end
这有什么变通方法吗?
答案 0 :(得分:1)
由于每个查询限制的单个不等式过滤器的限制,动态获得可以直接用于分页而无需进一步处理的单个结果列表是不可能的。相关GAE 4301 issue。
正如杰夫所说,过滤一个不等式(理想情况下是最严格的一个),然后进一步动态处理结果总是一个选项,如你所指出的那样低效,但如果你需要完全灵活的搜索,这是不可避免的。
您可以使用projection query来提高性能 - 减少从数据存储区传输到相关属性的数据量。
您还可以尝试执行2 keys-only queries,每个不等式一个,然后计算结果的交集 - 这可以更快地为您提供分页计数和实体列表(作为键)。最后,您可以通过直接键查找页面列表中的键来获取当前页面的实体,理想情况下是批处理(使用ndb.get_multi()
)。
根据预期用途,可能在某些情况下会有其他替代方案(当然需要额外的工作)。
您可以限制查询的范围。而不是在时间开始时查询所有Post
个实体,在某些情况下,仅仅某一年或一个月的结果就足够了。然后,您可以添加year
和/或month
Post
属性,您可以将这些属性包含在查询中作为相等过滤器,这可能会减少要动态处理的结果数量,例如,数百或更少。
对于典型的,经常使用的案例,您也可以完全避免查询。例如,如果预期用途是生成几种月度报告,那么您可以拥有一些Report
个实体,其中包含每个此类报告类型/月的Post
个密钥列表,您可以在{{1实体的相关属性发生了变化。您只需使用相应Post
实体中已有的列表,而不是查询Posts
个实体的报告。您还可以在生成时存储/缓存实际报告,以便直接重复使用(而不是在每次访问时重新生成它)。
答案 1 :(得分:0)
使用多个过滤器和不等式查询的另一种解决方法是使用Search API。 https://cloud.google.com/appengine/training/fts_adv/lesson1#query_options
来自文档:
例如,查询
job tag:"very important" sent < 2011-02-28
在任何字段中查找具有术语作业的文档,并且还包含 短语在标记字段中非常重要,以及之前的发送日期 2011年2月28日。
只需将数据从数据存储查询中的数据放入搜索文档中,然后对这些文档运行查询。