RavenDBなどのドキュメントデータベースが非リレーショナルであるとすると、複数のドキュメントに共通するデータの重複をどのように回避しますか?複製しても問題がない場合、そのデータをどのように維持しますか?
2 に答える
ドキュメントデータベースでは、データをある程度複製する必要があります。その程度は、システムとユースケースによって異なります。
たとえば、単純なブログとユーザー集計がある場合、次のように設定できます。
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; }
}
}
この例では、BlogUserクラスをBlogクラス内にネストし、Blogに関連付けられたUserAggregateのIdプロパティとNameプロパティを使用しています。これらのフィールドはブログクラスが関心を持っている唯一のフィールドであり、ブログが表示されているときにユーザーのユーザー名やパスワードを知る必要がないため、これらのフィールドを含めました。
これらのネストされたクラスはシステムのユースケースに依存するため、慎重に設計する必要がありますが、一般的な考え方は、1回の読み取りでデータベースからロードでき、必要なすべてのデータを含む集計を設計することです。それらを表示または操作します。
これにより、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クライアントは作業単位パターンを使用するため、これは実際にはこのメソッド以外の場所で発生するはずです。
私見の質問に対する「正しい」答えはありません。それは、複製するデータがどれだけ可変であるかに本当に依存します。
ドキュメントDBの設計とリレーショナルに関する多くの回答については、RavenDBのドキュメントを参照してください。ただし、ドキュメント構造の設計に関する考慮事項ドキュメントの「関連付けの管理」セクションを具体的に確認してください。つまり、ドキュメントDBは、共有データをドキュメントに埋め込みたくない場合に、IDによる参照の概念を使用します。これらのIDはFKとは異なり、完全性を確保して解決するのは完全にアプリケーション次第です。