架构升级和last_modified属性(GAE& NDB)

时间:2012-08-01 06:01:18

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

我刚刚使用mapreduce完成了在GAE数据存储上执行架构升级的基础。我们正在使用NDB,许多或我们的模型使用DateTimeProperty的auto_now关键字选项来设置last_modified属性。

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值,还是我们添加另一个属性或用我们可以控制的属性替换这些属性并手动设置值?


好的,所以共识似乎是我应该能够定义模型的替代版本,该版本仅由mapreduce代码使用,而不是面向用户的代码(我非常希望避免关闭网站进行架构升级)但我无法让它工作。

通过以下设置,面向用户的代码正常工作(更新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&amp; Guido求助。

欢呼声,

Ĵ

1 个答案:

答案 0 :(得分:1)

解决方案是在map / reduce代码中的所有模型定义中设置auto_now = False。

我建议以最少的错误机会这样做:

定义一个可以为True或False的全局常量,用于模型定义中的所有auto_now设置。然后,您必须仅更改该行,以便为所有模型将其从True更改为False。您甚至可以根据某些环境变量自动计算值。