保持数据库中某个实体的更新(差异)的最佳方法是什么?在StackOverflow,我们可以编辑问题和答案。然后我们可以查看我们想要的问题或答案的任何修订。例如:revisions一些随机问题。也许有人知道它是如何在StackOverflow中实现的?
为了清楚我的情况,我有一些实体(article
)包含一些字段(name
,description
,content
)。许多用户可以编辑同一篇文章。我想保留文章更新的历史(类似于版本控制),我想只保留差异,而不是更新文章的全部内容。顺便说一句,我使用PostgreSQL,但可以迁移到任何其他数据库。
UPD 打开赏金,所以这里有一些要求。你不需要完全满足它们。但如果你这样做会更好。然而,任何答案都非常感谢。所以我想要一个能力:
header
,description
或content
(如StackOverflow标题和内容中的更改),因此必须将其考虑在内。答案 0 :(得分:2)
在过去,我使用了diff-match-patch的优秀(和快速)结果。它适用于多种语言(我使用它的经验是在C#中)。我没有将它用于你所描述的过程(我们对合并感兴趣),但在我看来你可以:
如果你想加快速度,你可以将文章的最新版本缓存在它自己的行/表中,然而你可以组织一些东西,这样获得最新版本就是一个简单的SELECT。这样,您就拥有了初始版本,补丁列表和当前版本,为您提供了一些灵活性和速度。
由于您按顺序有一组补丁,因此获取该文章的任何版本只需将补丁应用到所需的补丁。
您可以take a look at the patch demo查看其补丁的外观,并了解它们的大小。
就像我说的那样,我并没有将它用于这种情况,但是diff-match-patch的设计或多或少都与你所说的完全相同。这个库位于我的简短软件列表中,当我对外部开发的库没有限制时,我可以使用它。
例如,您可以像这样设置表格(假设其他一些表格,如作者):
Articles
--------
id
authorId
title
content
timestamp
ArticlePatches
--------------
id
articleId
patchText
timestamp
CurrentArticleContents
----------------------
id
articleId
content
然后一些基本的CRUD可能看起来像:
插入新文章:
INSERT INTO Articles (authorId, title, content, timestamp)
VALUES(@authorId, @title, @content, GETDATE())
INSERT INTO CurrentArticleContents(articleId, content)
VALUES(SCOPE_IDENTITY(),@content)
GO
获取每篇文章的最新内容:
SELECT
a.id,
a.authorId,
a.title,
cac.content,
a.timestamp AS originalPubDate
FROM Articles a
INNER JOIN CurrentArticleContents cac
ON a.id = cac.articleId
更新文章的内容:
//this would have to be done programatically
currentContent =
(SELECT content
FROM CurrentArticleContents
WHERE articleId = @articleId)
//using the diff-match-patch API
patches = patch_make(currentContent, newContent);
patchText = patch_toText(patches);
//setting @patchText = patchText and @newContent = newContent:
(INSERT INTO ArticlePatches(articleId, patchText, timestamp)
VALUES(@articleId, @patchText, GETDATE())
INSERT INTO CurrentArticleContents(articleId, content, timestamp)
VALUES(@articleId, @newContent, GETDATE())
GO)
在特定时间点获取文章:
//again, programatically
originalContent = (SELECT content FROM Articles WHERE articleId = @articleId)
patchTexts =
(SELECT patchText
FROM ArticlePatches
WHERE articleId = @articleId
AND timestamp <= @selectedDate
ORDER BY timestamp ASCENDING)
content = originalContent
foreach(patchText in patchTexts)
{
//more diff-match-patch API
patches = patch_fromText(patchText)
content = patch_apply(patches, content)[0]
}
答案 1 :(得分:1)
我在工作场所有类似的问题。
我在更新后使用触发器将所有需要的数据记录到另一个表中(当然你只能保存差异字段),而真正的表上存在新的,而日志则存在于另一个表中表