令人困惑的App Engine Datastore问题(ListProperty)

1 投票
2 回答
1370 浏览
提问于 2025-04-15 16:16

好的,我在本地和云端的gae上都有相同的python代码。

当我在本地存储一个实体时,ListProperty字段的元素类型是datetime.datetime,在数据存储查看器中显示如下:

2009-01-01 00:00:00,2010-03-10 00:00:00

而当我在云端存储相同的内容时,查看器显示:

[datetime.datetime(2009, 1, 1, 0, 0), datetime.datetime(2010, 3, 9, 0, 0)]

为什么会有不同的表现形式呢?

这本来不太困扰我,只有在我在云端查询这个字段时,查询却找不到匹配的实体(在本地是可以找到的)——这让我觉得可能是这种不同的表现形式导致了问题。我再强调一下,代码是完全一样的。

有没有人能想出这是为什么,以及解决办法呢?

更新:

我的查询如下(使用了过滤器):

from x import y
from datetime import datetime
from google.appengine.ext import db

q = y.EntityType.all().filter('displayDateRange <=',datetime.now()).filter('displayDateRange >=',datetime.now())

usersResult = q.fetch(100)
print `len(usersResult)`

结果应该是1,但实际上是0。

实际上,问题只出在指定值为datetime.datetime的ListProperty上——在云端,StringListProperty的查询是正常的。

我在本地和云端的交互控制台上都尝试了原始过滤器,云端没有返回任何结果。所以我猜这可能是数据存储的问题,一定与存储格式有关——在两个数据存储中,我只有一个实体值,ListProperty看起来是这样的:

2009-01-01 00:00:00,2010-03-09 00:00:00
[datetime.datetime(2009, 1, 1, 0, 0), datetime.datetime(2010, 3, 9, 0, 0)]

分别在本地和云端。

有什么想法吗?

进一步更新

我把datetime.now()替换成了硬编码的datetime对象——现在的过滤器看起来是这样的:

y.EntityType.all().filter('displayDateRange <=',datetime(2009,11,24)).filter('displayDateRange >=',datetime(2009,11,24))

注意,上面的datetime ListProperty范围是从2009年1月1日到2010年3月9日,这应该能返回上面的实体——我在本地开发服务器上尝试了这个完全相同的过滤器,结果是可以的。而在云端,由于datetime.datetime ListProperty的不同表现形式,结果却不行。

注意,这个是根据当前最佳实践来过滤日期范围得来的。

有没有人能想出可能出错的地方?

2 个回答

1

你看到的问题很明显是在本地情况下进行字符串转换(调用了 __str____unicode__),而在云端则显示了数据的表示形式(repr)。不过,这种输出结果的差异不应该是你在云端查询失败的原因。

你具体的查询是什么呢?

更新:在了解了查询后:

我不太明白你为什么要使用这些过滤条件:

.filter('displayDateRange <=',datetime.now()).filter('displayDateRange >=',datetime.now())

这里有两个问题:

  • 你调用了 datetime.now() 两次,这可能会得到不同的结果,导致结果集为空。在一个负载较高的服务器上,多个线程或进程同时运行时,这种情况尤其常见。

  • 你可能想用上面的这对过滤条件来检查是否相等。但如果 datetime.now() 返回的时间精度和数据库中存储的时间精度不同,这样的检查就行不通。一般来说,在浮点数和亚秒级时间值的情况下,检查相等性并不是个好主意。

你想通过这样一对过滤条件达到什么目的呢?

2

简单来说:现在这个问题被归类为应用引擎开发服务器版本的一个错误,并且在生产环境的云数据存储中不再支持。

我在一篇博客文章中详细解释了这个问题,建议你看看第三点。

撰写回答