我刚刚完成了使用mapreduce为GAE的数据存储上执行模式升级设置基础。我们正在使用NDB,并且很多或我们的模型都会使用DateTimeProperty的auto_now关键字选项来设置last_modified属性。Schema升级和last_modified属性(GAE和NDB)
last_modified = ndb.DateTimeProperty(auto_now=True)
当然,在运行更新实体的mapreduce作业时,last_modified属性也会更新,这实际上并不是我们想要的。
def upgrade_entity(entity):
# modify entity
yield op.db.Put(entity)
根据文档,您可以覆盖auto_now_add设置属性的值,但不会覆盖auto_now。
我现在认为可能有其他情况,我们不希望last_modified属性也被更新。
那么,有什么办法来保存实体的last_modified值,或者我们添加另一个属性或替换这些属性与我们可以控制,只需手动设置值?
OK,这样的共识似乎是,我应该能够定义一个仅用于映射精简代码,而不是面向代码的用户模型的替代版本(我非常想避免关闭该站点以进行模式升级),但是我一直无法得到这个工作。
通过以下设置,面向用户的代码能够正常工作(更新last_modifed),直到我运行也正常工作的mapreduce(不会更新last_modified)。运行mapreduce的用户面临的代码不再更新LAST_MODIFIED ..
models.py
class MyModel(ndb.Model):
# model used by user facing code
last_modified = ndb.DateTimeProperty(auto_now=True)
upgrade.py
class MyTmpModel(ndb.Model):
# model used by mapreduce code
@classmethod
def _get_kind(cls):
return 'MyModel'
last_modified = ndb.DateTimeProperty(auto_now=False)
def upgrade_model(entity):
# mapper function
# modify entity
yield op.db.Put(entity)
mapreduce.yaml
mapreduce:
- name: Upgrade Model
mapper:
input_reader: mapreduce.input_readers.DatastoreInputReader
handler: upgrade.upgrade_model
params:
- name: entity_kind
default: upgrade.MyTmpModel
确定后,我要把我的问题放在这里在我一直在dev_server中测试它,以及与真正的gae服务器相比,在那里运行的方式有所不同。我的结论是,在dev_server所有的代码在同一个进程中运行,并在不同的模型版本不沿着..从NDB模型文档使用:
的应用程序不应该使用相同的定义两个模型类善良,即使他们生活在不同的模块中。一个应用程序的种类被认为是全局的“命名空间”。
我以为我可以依靠的事实,真正的GAE服务器上的MapReduce代码将在单独的情况下运行,这些版本冲突不会发生,也不会影响用户面临服务器实例使上面的设置应该按预期工作。
感谢Tim & Guido为您提供帮助。
欢呼声,
Ĵ
您可以添加auto_now未设置为True的版本,并针对该版本运行您的mapreduce。它不会为您提供您想要的细粒度控制,但可能是您的模式迁移过程中最简单的方法。蒂姆,感谢 – 2012-08-01 06:25:46
。你让它听起来很简单,所以也许它是......而且这也应该适用于使模型成为Expando的子类以去除属性..所以现在我想我可以在某处定义模型的临时版本并使用它在mapreduce配置中,只要它与我的实际模型具有相同的类名称? (了解更多关于Python每天如何工作的信息..以及GAE和NDB ..) – lecstor 2012-08-01 06:45:48
hmm ..好的,为了记录,在我的mapper函数中定义我的“临时”版本的模型,并在mapreduce配置中引用它,但后来当我进入我的应用程序并修改了实体时,last_modified属性没有更新,因此它似乎在模型的“临时”版本中也覆盖了我的真实版本。不幸的是,这意味着任何使用该应用程序的人都将使用该模型的“临时”版本。 – lecstor 2012-08-01 11:50:34