【问题标题】:App Engine: ReferencePropertyResolveError in Google App Engine?App Engine:Google App Engine 中的 ReferencePropertyResolveError?
【发布时间】:2012-01-08 13:33:59
【问题描述】:

请帮助我理解为什么 App Engine (Python 2.5, High Replication) 上出现此错误?

回溯(最近一次通话最后): __call__ 中的文件“/base/python_runtime/python_lib/versions/1/google/appengine/ext/webapp/_webapp25.py”,第 703 行 handler.post(*groups) 文件“/base/data/home/apps/s~apptest/1.354937136776013205/main.py”,第 963 行,在帖子中 get_purchases_for_user(pur.user,pur.car.model) 文件“/base/python_runtime/python_lib/versions/1/google/appengine/ext/db/__init__.py”,第 3592 行,在 __get__ reference_id.to_path()) ReferencePropertyResolveError:ReferenceProperty 无法解析:[u'User',374836L]

上下文:该应用程序是关于购买汽车的建议。

什么时候发生:大约每 100 笔交易大约 2 次,所以我真的不知道什么时候也不知道为什么。

其中代码中的对象pur定义为:

allPurchases = models.Purchase.all()
for pur in allPurchases:
   car = get_purchases_for_user(pur.user, pur.car.model)

我之前也放了这段代码,我得到了同样的错误,当然是引用这一行

logging.error("Object user: %s, Car Model %s" % {str(pur.user), pur.car.model})

所以,问题不在于 get_purchases_for_user 函数

这些是数据存储区中的模型:

class User(db.Model):
    username = db.StringProperty(
        required=True)
    name = db.StringProperty(
        required=True)
    email = db.EmailProperty(
        required=True)
    password = db.StringProperty(
        required=True)

class Car(db.Model):
    model = db.StringProperty()
    name = db.StringProperty()
    year = db.DateTimeProperty()

class Purchase(db.Model):
    user = db.ReferenceProperty(User,
        collection_name='recommendations')
    car = db.ReferenceProperty(Car,
        collection_name='recommendations')
    when = db.DateTimeProperty(
        auto_now=True)

【问题讨论】:

  • 您确认您确实有一个 ID 为 374836User 实体吗?
  • 不,我没有。但是应用程序如何调用一个从未存在过的实体
  • 我的猜测是它在创建 ReferenceProperty 时就存在,然后在没有考虑参照完整性的情况下被删除。除非你做了一些疯狂的事情,比如以编程方式在 ReferenceProperty 中创建 Key 而不指向实际实体。
  • 不可能。该应用程序从不删除用户。我完全确定这一点
  • 那么,您确认用户存在了吗?只需 2 分钟,对可能出错的事情的假设数量将减半。

标签: python google-app-engine google-cloud-datastore


【解决方案1】:

您的实体有一个不存在的 ReferencePropertyUser 实体 - 很可能是因为它已被删除。您可以添加代码来捕获此特定异常,并以适合您的应用程序的任何方式处理它。

【讨论】:

    【解决方案2】:

    我倾向于问题在于数据存储的高复制和缺乏保证的一致性。来自谷歌文档:

    但是,在 High Replication 数据存储中,跨实体组的查询(换句话说,非祖先查询)可能会返回陈旧的结果。为了在 High Replication 环境中返回强一致的查询结果,您需要在单个实体组上进行查询。这种类型的查询称为祖先查询。

    祖先查询之所以有效,是因为实体组是一个一致性单元:所有操作都应用于整个组。在整个实体组更新之前,祖先查询不会返回数据。因此,对实体组的祖先查询返回的数据是强一致的。

    如果您的应用程序依赖于某些查询的高度一致的结果,您可能必须更改应用程序存储实体的方式。本页面讨论了处理存储在 High Replication 数据存储中的数据的最佳实践。让我们分别使用主/从和高复制数据存储的示例留言簿应用程序来看看这是如何工作的。

    如此有效,您可能正在查询刚刚编写但尚未传播到整个数据存储区的内容。结果,当您引用该属性时,就好像它从未存在或被删除一样。

    看起来您正在使用 .all() 来检索数据。如果可能的话,我建议重写它以使用 GQL 和祖先查询。或者可能及时限制数据以允许传播。关于祖先查询的文档:http://code.google.com/appengine/docs/python/datastore/queries.html#Ancestor_Queries

    【讨论】:

    • 不正确 - 数据存储区获取操作将始终返回实体(如果存在)。
    • 尼克,请您详细说明一下 - 我是不是误解了,还是引用的文档不正确?
    • A ReferenceProperty 执行数据存储获取操作以检索引用的实体。数据存储区总是返回一个实体(如果存在) - 最终一致性不适用。
    • 谢谢!如果您也可以让某人在文档中包含该用例,那就太好了。
    • 我不确定我是否理解 - 您希望在文档中包含什么?
    猜你喜欢
    • 1970-01-01
    • 2012-05-15
    • 1970-01-01
    • 1970-01-01
    • 2019-05-17
    • 2013-10-20
    • 2011-01-22
    • 2013-08-03
    • 1970-01-01
    相关资源
    最近更新 更多