我是MongoDB的新手。我正在尋找一種方法來記錄所有插入,更新或刪除文檔的操作,以便維護更改歷史記錄。因此,例如,我想知道特定文檔中的特定字段何時更新,更新的內容以及之前的內容。這適用於使用C#MongoDB驅動程序的ASP.NET C#應用程序,因此我不介意該解決方案是否涉及Mongo本身或C#代碼。在MongoDB中記錄插入,更新和刪除操作
例如:
ID |Timestamp |Operation|ObjectID | PrevValue | NewValue
-----------------------------------------------------------------------------------------------
2153|1411390359| i |245245...| null |{name: "John Smith", age: 35}
2154|1411390471| u |245245...| {age: 35} | {age: 36}
2155|1411390478| d |245245...|{name: "John Smith", age: 36}| null
它不必遵循這種確切的格式,但它應該可以很容易地跟蹤歷史。
我看了一下MongoDB oplog,但它看起來不太適合這種工作。例如,爲了識別對文檔的更改,它看起來像我必須查找兩個條目(文檔的最新更新條目和先前的文檔條目,可能是更新或插入),然後比較每個字段在文件中檢查哪個(哪些)被改變了,他們的原始值是什麼。爲了提高效率,我寧願僅僅擁有一個包含所有這些信息的條目,以防需要許多查詢來檢查對許多文檔的更改。我想確保使用日誌儘可能無痛苦。如果日誌存儲在MongoDB集合中,每個條目的文檔(如oplog)使查詢變得容易,這也是理想的選擇。
在MongoDB(oplog除外)中是否有一個功能可以完成這樣的事情?如果沒有,是否有一個好的第三方工具可以?或者我必須手動實現它?
編輯:一些更多的細節:
1)OPLOG的另一個問題是封頂的,所以一旦它運行的空間,它會刪除最早的條目。我想保留一份全部歷史的列表,不管它多大。
2)日誌的內容將以某種方式顯示給用戶,用戶可能會請求查看更改的歷史記錄。這不僅適用於數據庫管理員的內部記錄,因此需要根據需要進行查詢。
編輯#2:我一直在頭腦風暴這個問題的一些解決方案,但他們都仍然有一些缺陷,所以我希望進一步的投入,如果有人有一個更好的主意。
可能的解決方案1:爲每個版本(使用版本#)和標記(如果它已被刪除)保留一個單獨的文檔。
實現:爲每個文檔添加一個「版本」字段。版本1是初始狀態(表示插入),後續版本表示更新,這些更新放置在單獨的新創建的文檔中,而不是更新舊版本。版本-1意味着文檔現在被視爲「已刪除」。顯然這不涉及實際的日誌文件。
問題:如果我需要一次加載多個文檔的歷史更改數據,則需要大量空間和成本進行查詢。也很難確定哪些特定的字段發生了變化,除非我還包含前一版本的「更改」字段,這也增加了更多空間。如果舊版本也需要搜索,也可能會使用最新版本進行查詢時會變得麻煩和昂貴(無法確定哪個版本是當前版本)。即使有另一面旗幟說它是最新的,我仍然需要確保旗幟隨時根據需要進行更新。
可能的解決方案2:維護修訂歷史爲每個文檔的子文檔場
實現:每個文件都有一個包含有一個版本號每個修訂了「RevisionHistory」字段。更容易查找單個文檔的歷史數據
問題:由於新字段的原因,跨多個文檔執行歷史記錄查詢的難度加大,並且執行更新的API調用更加複雜。特別是,我需要在過去X小時內(X由用戶提供)顯示所有更改,作爲實施的一部分,如果使用此方法,則需要掃描所有文檔。
可能的解決方案3:添加手動日誌()函數調用從C#
實現:每次MongoDB的C#驅動程序的API調用一個新的操作,有程序員還添加一行調用一個特殊的函數來處理日誌文件的記錄。
問題:取決於程序員實際記住手動添加此函數調用並正確調用它。一個簡單的錯誤會導致日誌系統變得不可靠。
可能的解決方案4:創建一個從C#
執行情況的API操作的包裝函數:程序員不直接調用API,但調用處理的工作爲他們的功能。這需要很多工作,在包裝函數級別處理每種可能的相關API調用類型,但是一致且可靠。抽象出DB訪問的好方法,以便在錯誤的低級別API調用中不會出現問題。有些不在DAL上工作的人可以調用包裝函數,函數會計算出詳細信息,包括日誌記錄。
問題:開發包裝函數更具挑戰性,因爲它需要考慮修改文檔的所有可能的API調用。
現在我傾向於解決方案4.但是,如果有更簡單的方法來做到這一點,我有興趣聽到它。