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