RavenDb學習(四)處理文件相關性
阿新 • • 發佈:2022-04-29
RavenDb是文件型資料庫,但是我們常常也需要定義物件之間的關係,那RavenDb當中是如何處理的呢? RavenDb提供了優雅的解決方式,使用正確的話,可以減少資料開銷以及網路擁堵 Denormalization 第一種就是反規範化,下面是一個訂單的JSON格式 在Order這個訂單當中我們把我們需要的客戶資訊(名字)也儲存下來了,使用的時候,它直接就讀出來了。 { // Order document with id: orders/1234 "Customer": { "Name": "Itamar", "Id": "customers/2345" }, Items: [ { "Product": { "Id": "products/1234", "Name": "Milk", "Cost": 2.3 }, "Quantity": 3 } ] } 初始的類設計如下: public class Order { public string CustomerId { get; set; } public string[] SupplierIds { get; set; } public Referral Refferal { get; set; } public LineItem[] LineItems { get; set; } public double TotalPrice { get; set; } } public class Customer { public string Name { get; set; } public string Address { get; set; } public short Age { get; set; } public string HashedPassword { get; set; } } 在Order中持有下面這個反規範化的類,而不只是CustomerId public class DenormalizedCustomer { public int Id { get; set; } public string Name { get; set; } public string Address { get; set; } } Includes 1)RavenDb提供了這個Includes的功能去限制反規範化,上一種方式是直接儲存了另外一個物件的一些屬性,這種方式只是儲存了一個引用,當根物件被載入的時候,和它關聯的選項也會預載入。 我們可以這樣做: var order = session.Include<Order>(x => x.CustomerId) .Load("orders/1234"); //這一句不會在服務端執行 var cust = session.Load<Customer>(order.CustomerId); 2)載入多個文件 同時載入"orders/1234", "orders/4321" var orders = session.Include<Order>(x => x.CustomerId) .Load("orders/1234", "orders/4321"); foreach (var order in orders) { // this will not require querying the server! var cust = session.Load<Customer>(order.CustomerId); } 另外一種用法: var orders = session.Query<Order>() .Customize(x => x.Include<Order>(o => o.CustomerId)) .Where(x => x.TotalPrice > 100) .ToList(); foreach (var order in orders) { // this will not require querying the server! var cust = session.Load<Customer>(order.CustomerId); } 這裡面有兩個通道,當呼叫Load()方式時,呼叫了Results channel,第二個是 Includes channel,被包含的文件是通過它來返回的,並且儲存在session cache當中。 3)一對多Includes 一個訂單,多個提供商 var order = session.Include<Order>(x => x.SupplierIds) .Load("orders/1234"); foreach (var supplierId in order.SupplierIds) { // this will not require querying the server! var supp = session.Load<Supplier>(supplierId); } 4)二級包含關係 二級包含關係是值,Order類的屬性裡面沒有,是在Order類的屬性Referral的屬性當中有 public class Referral { public string CustomerId { get; set; } public double CommissionPercentage { get; set; } } var order = session.Include<Order>(x => x.Refferal.CustomerId) .Load("orders/1234"); // this will not require querying the server! var referrer = session.Load<Customer>(order.Refferal.CustomerId); 它也支援集合 var order = session.Include<Order>(x => x.Refferal.CustomerId) .Load("orders/1234"); // this will not require querying the server! var referrer = session.Load<Customer>(order.Refferal.CustomerId); 5)lucene query var orders = session.Advanced.LuceneQuery<Order2>() .Include(x => x.Customer2Id) .WhereGreaterThan(x => x.TotalPrice, 100) .ToList(); foreach (var order in orders) { // this will not require querying the server! var cust2 = session.Load<Customer2>(order.Customer2Id); } var orders = session.Advanced.LuceneQuery<Order2>() .Include("CustomerId") .WhereGreaterThan(x => x.TotalPrice, 100) .ToList(); foreach (var order in orders) { // this will not require querying the server! var cust2 = session.Load<Customer2>(order.Customer2Id); } Combining Approaches 這種是把前兩種方式結合起來了 public class Order3 { public DenormalizedCustomer Customer { get; set; } public string[] SupplierIds { get; set; } public Referral Refferal { get; set; } public LineItem[] LineItems { get; set; } public double TotalPrice { get; set; } } var order = session.Include<Order3, Customer2>(x => x.Customer.Id) .Load("orders/1234"); // this will not require querying the server! var fullCustomer = session.Load<Customer2>(order.Customer.Id);