2012-08-01 77 views
1

我剛剛完成了使用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爲您提供幫助。

歡呼聲,

Ĵ

+0

您可以添加auto_now未設置爲True的版本,並針對該版本運行您的mapreduce。它不會爲您提供您想要的細粒度控制,但可能是您的模式遷移過程中最簡單的方法。蒂姆,感謝 – 2012-08-01 06:25:46

+0

。你讓它聽起來很簡單,所以也許它是......而且這也應該適用於使模型成爲Expando的子類以去除屬性..所以現在我想我可以在某處定義模型的臨時版本並使用它在mapreduce配置中,只要它與我的實際模型具有相同的類名稱? (瞭解更多關於Python每天如何工作的信息..以及GAE和NDB ..) – lecstor 2012-08-01 06:45:48

+0

hmm ..好的,爲了記錄,在我的mapper函數中定義我的「臨時」版本的模型,並在mapreduce配置中引用它,但後來當我進入我的應用程序並修改了實體時,last_modified屬性沒有更新,因此它似乎在模型的「臨時」版本中也覆蓋了我的真實版本。不幸的是,這意味着任何使用該應用程序的人都將使用該模型的「臨時」版本。 – lecstor 2012-08-01 11:50:34

回答

1

解決的辦法是設置auto_now =假在地圖上所有的模型定義/減少代碼。

我與出錯的機會最小這樣的建議:

定義一個全局變量,可以是真或使用爲模型中定義的所有auto_now設置爲False。然後,您必須僅更改所有型號的一條線,將其從True更改爲False。您甚至可以根據某個環境變量自動計算值。

+0

。那麼我可以在哪裏設置一個env變量來區分面向用戶的代碼和mapreduce代碼?計算何時何地完成? (我已經添加了我的tmp模型嘗試到我原來的問題) – lecstor 2012-08-01 22:35:59

+0

再次感謝,我已經添加了我的結論到原來的問題。 – lecstor 2012-08-02 00:56:28

+2

其實我認爲你使用相同*版本*的應用程序你的地圖/減少至於常規的代碼?不要那樣做,他們會混在一起。相反,將您的mapreduce作業部署爲不同的版本(只需編輯app.yaml)。然後你可以檢查環境中的版本,例如os.getenv('CURRENT_VERSION_ID')。split('。')[0] – 2012-08-03 14:58:03