1

我刚刚完成了使用 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..

模型.py

class MyModel(ndb.Model):
    # model used by user facing code
    last_modified = ndb.DateTimeProperty( auto_now=True )

升级.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 代码将在单独的实例中运行,并且不会发生这些版本冲突,也不会影响面向用户的服务器实例,因此上述设置应该按预期工作.

感谢蒂姆和圭多的帮助。

干杯,

Ĵ

4

1 回答 1

1

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

我建议以最少的错误机会执行此操作:

定义一个可以为 True 或 False 的全局常量,用于模型定义中的所有 auto_now 设置。然后,您只需更改那一行,即可将所有模型的从 True 更改为 False。你甚至可以让它根据一些环境变量自动计算值。

于 2012-08-01T17:26:33.640 回答