6

鉴于 RavenDB 等文档数据库是非关系型的,如何避免重复多个文档共有的数据?如果可以复制数据,您将如何维护这些数据?

4

2 回答 2

12

使用文档数据库,您必须在某种程度上复制数据。该程度将取决于您的系统和用例。

例如,如果我们有一个简单的博客和用户聚合,我们可以将它们设置为:

  public class User 
  {
    public string Id { get; set; }
    public string Name  { get; set; }
    public string Username  { get; set; }
    public string Password  { get; set; }
  }

  public class Blog
  {
     public string Id  { get; set; }
     public string Title  { get; set; }

     public class BlogUser
     {
       public string Id  { get; set; }
       public string Name  { get; set; }
     }
  }

在此示例中,我在 Blog 类中嵌套了一个 BlogUser 类,其中包含与 Blog 关联的 User Aggregate 的 Id 和 Name 属性。我已经包含了这些字段,因为它们是 Blog 类唯一感兴趣的字段,在显示博客时不需要知道用户的用户名或密码。

这些嵌套类将取决于您的系统用例,因此您必须仔细设计它们,但总体思路是尝试设计可以通过单次读取从数据库加载的聚合,它们将包含所需的所有数据显示或操作它们。

这就引出了当 User.Name 被更新时会发生什么的问题。

对于大多数文档数据库,您必须加载属于已更新用户的所有 Blog 实例并更新 Blog.BlogUser.Name 字段并将它们全部保存回数据库。

Raven 略有不同,因为它支持更新的集合函数,因此您可以对 RavenDB 运行单个更新,这将更新用户博客的 BlogUser.Name 属性,而无需加载它们并单独更新它们。

在 RavenDB 中对所有博客进行更新的代码(手动方式)将是:

  public void UpdateBlogUser(User user)
  {
    var blogs = session.Query<Blog>("blogsByUserId")
                  .Where(b.BlogUser.Id == user.Id)
                  .ToList();

    foreach(var blog in blogs)
       blog.BlogUser.Name == user.Name;

    session.SaveChanges()
  }

我在 SaveChanges 中添加了一个示例。RavenDB 客户端使用工作单元模式,所以这应该真的发生在这个方法之外的某个地方。

于 2010-06-08T13:03:17.600 回答
2

恕我直言,您的问题没有一个“正确”的答案。这实际上取决于您复制的数据的可变性。

查看RavenDB 文档以获取有关文档数据库设计与关系的大量答案,但请特别查看文档结构设计注意事项文档的“关联管理”部分。简而言之,当文档数据库不想在文档中嵌入共享数据时,它们会使用 ID 引用的概念。这些 ID 与 FK 不同,它们完全取决于应用程序来确保完整性和解析。

于 2010-06-05T22:00:33.017 回答