2014-10-02 38 views
11

我想在僅追加數據存儲中重新實現一些現有的SQLAlchemy模型;僅追加意味着對象僅使用INSERT語句更新,不使用UPDATE或DELETE語句。如何在SQLAlchemy中實現僅追加版本化模型

UPDATE和DELETE語句將被替換爲增加版本的另一個INSERT。會有一個is_deleted標誌,取而代之的DELETE,新版本is_deleted=True將被創建:

id | version | is_deleted | name  | description ... 
---- --------- ------------ ----------- --------------- 
    1 |  1 |   F | Fo  | Text text text. 
    1 |  2 |   F | Foo  | Text text text. 
    2 |  1 |   F | Bar  | null 
    1 |  3 |   T | Foo  | Text text text.   

此外,

我知道如何解決大多數問題,但我在SQLAlchemy中的事件掛鉤,將處理這需要在更新完成&刪除某些事情掙扎。

SQLAlchemy文檔已經有一些版本控制的基本示例。 versioned rows示例接近我想要的,但它們不處理(1)刪除和(2)外鍵關係。

(1)刪除。我知道有一個session.deleted字段,我將以類似的方式迭代它,以便在versioned_rows.py示例中迭代session.dirty - 但是,如何從要刪除的列表中取消標記項目&創建新項目? (2)上面提到的例子只處理父子關係,它的做法(過期關係)似乎需要每個模型的自定義代碼。 (2.1)有沒有辦法讓這個更靈活? (2.2)是否可以將SQLAlchemy的relationship()配置爲針對給定的外鍵返回max(版本)的對象?

+1

您正在尋找的術語是「軟刪除」。我不是很瞭解SQLAlchemy,但也許會幫助你。我個人可能會用數據庫端的觸發器來做到這一點。 – 2014-10-02 15:39:08

+0

謝謝 - 我發現這個軟刪除,這有助於我的問題的第一部分http://stackoverflow.com/questions/23198801/sqlalchemy-using-aliased-in-query-with-custom-primaryjoin-relationship使用數據庫觸發器對我來說不是一種選擇,因爲我的模型頻繁更改,觸發器不能通過像alembic這樣的遷移工具很好地處理。 – lyschoening 2014-10-03 09:34:26

+1

好奇的問題,我也很想看到處理這個問題的一些例子。關於鏈接到max(版本),更好的方法可能是沒有針對Head版本的版本號,因此您可以直接加入最新的記錄(version == None)。數據是否需要在同一個表中?只是想知道版本控制對象系統(創建第二個表,blah_history)是否可以簡化http://docs.sqlalchemy.org/en/latest/orm/examples.html#versioning-objects。它還處理刪除,因爲整個版本歷史記錄在輔助表中可用。 – 2014-10-12 02:05:02

回答

1

將是ORM工具不可知的一個有用的事情可能是「而不是」觸發器。例如,您可以捕獲更新前的事件,並使用新更新的數據打開增量版本號。

對於postgresql,它們是詳細的here

當然,你將不得不有模型的變化(在PK的等)。爲了獲取「最新版本」(通過視圖圖層或sql alchemy where子句/等),您可能必須有遞歸查詢來研究性能影響,這是值得的。 )

0

這聽起來很瘋狂,但實際上使用不同類型的數據庫可能會更好。你知道Datomic?。傳統的RDBMS和這種類型的系統之間的根本區別之一是沒有就地更新,這是RDBMS如何更新磁盤上的文件。相反,所有內容都是版本控制的,您可以返回到數據庫的所有以前版本,以查看每個資源的每個更改。此外,只需將感興趣的時間作爲參數傳遞,您就可以在特定時刻輕鬆查看整個數據庫的狀態。還有很多其他有趣的優勢,我強烈建議看看Rich Hickey的一些會談,例如this one。這絕對是一種與你目前嘗試的方法截然不同的方法,但人們必須考慮這種努力是否會在每一步的每一步都與工具相抗衡,並以一種他們真正沒有的方式使用它們(RDBMS,ORM,遷移經理......)。相反,您可以將這種複雜性降低到一層,並讓其他種類的數據庫爲您處理。