我是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.但是,如果有更简单的方法来做到这一点,我有兴趣听到它。