我有许多可在某些时段预订的物品。例如。一个网球场。因此,每个项目都有许多相关的可用性槽,每个槽都由begintime和endtime定义。 Begintime和endtime被定义为datetime-objects,因此存储从09.00到11.30的可用性槽,例如。 2013-12-13 09.00(开始时间)至2013-12-13 11.30(结束时间)。
当预订请求进入时,我需要知道网球场是否适用于所需的时段。
所以我尝试根据开始时间和结束时间过滤可用性插槽,我的查询如下所示:
desired_availability_start = datetime(2013, 12, 13, 9,0,0)
desired_availability_end = datetime(2013, 12, 13, 10,0,0)
availability_slots = self.availability_slots.filter("begin <= ", desired_availability_start).filter("end >= ", desired_availability_end).fetch(limit=10)
但是我收到以下错误
invalid filter: Only one property per query may have inequality filters (>=, <=, >, <)
因为我试图过滤开始和结束属性。
根据输入以及主题Inequality Filter in AppEngine Datastore和BadFilterError: invalid filter: Only one property per query may have inequality filters (<=, >=, <, >)上的其他一些帖子,我目前的解决方案是首先过滤开始:
filtered_availability_slots = self.availability_slots.filter("begin <= ", desired_availability_start).fetch(limit=10)
然后过滤结束并将过滤后的项目附加到列表中:
final_availability_slots = []
for availability in filtered_availability_slots:
if availability.end >= desired_availability_end:
final_avaialability_slotes.append(availability)
但这是实现我想要实现的目标的最佳方式吗?
我正在使用Google App Engine和Python
感谢任何帮助
感谢 托马斯
答案 0 :(得分:2)
正如我猜您已经知道的那样,您不能使用多个数据存储区中的不等过滤器使用多个变量。除非您确实需要,否则您只能使用“开始”时间进行过滤,并且仍能获得非常准确的结果。
calitem = self.appointments.filter("begin >= ", start).filter("begin <= ", end).fetch(limit=10)
如果您真的需要,使用您的应用程序逻辑,您只能显示不超出“结束”值的项目。我没有看到任何其他方式。
答案 1 :(得分:1)
有点不清楚你在问什么。目前尚不清楚你是否理解这个问题:你试图使用两个不等式过滤器,而这是不允许的。做不到。
您必须解决此数据存储限制。
最基本的选择是自己暴力。使用一个过滤器,并自己手动过滤掉结果。过滤begin
并对end
进行排序可能有所帮助,但您必须完成搜索并选择所需的实际实体。
calitem = [x for x in self.appointments.filter("begin >= ", start).filter("begin <= " end) if x.end <= end]
在大多数情况下,您需要重新构建数据,以便不需要两个不等式过滤器。这可能是也可能是不可能的。
我正在猜测你正在做什么,但是如果你想根据他们的日历在上午11点看某人是否忙,那么这样做的方法是:
答案 2 :(得分:0)
我有类似的要求:从数据存储区中挑选出现在应该渲染/交付的实体。由于数据存储无法处理此问题,因此需要应用程序逻辑。我对满足约束两端的键进行了两次单独的查询,然后取出它们的交集:
satisfies "begin" criteria: k1, k3, |k4, k5|, k6
--------+------+----
satisfies "end" criteria: k2, |k4, k5|, k7, k8
“开始”和“结束”的交集是键k4, k5
。
now = datetime.now()
start_dt_q = FooBar.all()
start_dt_q.filter('start_datetime <', now)
start_dt_q.filter('omit_from_feed =', False)
start_dt_keys = start_dt_q.fetch(None, keys_only=True)
end_dt_q = FooBar.all()
end_dt_q.filter('end_datetime >', now)
end_dt_q.filter('omit_from_feed =', False)
end_dt_keys = end_dt_q.fetch(None, keys_only=True)
# Get "intersection" of two queries; equivalent to
# single query with multiple criteria
valid_dt_keys = list(set(start_dt_keys) & set(end_dt_keys))
然后我迭代这些键获取我需要的实体:
for key in valid_dt_keys:
foobar = FooBar.all().filter('__key__ =', key).get()
...
OR:
foobars = FooBar.all().filter('__key__ IN', valid_dt_keys)
for foobar in foobars:
...