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
        },

    }
  ]
}

初始的类设计如下:
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

)RavenDb提供了这个Includes的功能去限制反规范化,上一种方式是直接保存了另外一个对象的一些属性,这种方式只是保存了一个引用,当根对象被加载的时候,和它关联的选项也会预加载。
我们可以这样做:
var order = session.Include<Order>(x => x.CustomerId)
    .Load("orders/1234");
//这一句不会在服务端执行
var cust = session.Load<Customer>(order.CustomerId);

)加载多个文档
同时加载"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 > )
    .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当中。

)一对多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);
}

)二级包含关系

二级包含关系是值,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);

)lucene query
var orders = session.Advanced.LuceneQuery<Order2>()
    .Include(x => x.Customer2Id)
    .WhereGreaterThan(x => x.TotalPrice, )
    .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, )
    .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);

RavenDb学习(四)处理文档相关性的更多相关文章

  1. MongoDB学习笔记:文档Crud Shell

    MongoDB学习笔记:文档Crud Shell   文档插入 一.插入语法 db.collection.insertOne() 将单个文档插入到集合中.db.collection.insertMan ...

  2. RabbitMQ学习系列四-EasyNetQ文档跟进式学习与实践

    EasyNetQ文档跟进式学习与实践 https://www.cnblogs.com/DjlNet/p/7603554.html 这里可能有人要问了,为什么不使用官方的nuget包呐:RabbitMQ ...

  3. ElasticSearch 5学习(8)——分布式文档存储(wait_for_active_shards新参数分析)

    学完ES分布式集群的工作原理以及一些基本的将数据放入索引然后检索它们的所有方法,我们可以继续学习在分布式系统中,每个分片的文档是被如何索引和查询的. 路由 首先,我们需要明白,文档和分片之间是如何匹配 ...

  4. python 学习之FAQ:文档内容写入报错

    2017.3.29 FAQ 1. 文档内容写入报错 使用with open() as file: 写入文档时,出现'\xa9'特殊字符写入报错,通过print('\xa9')打印输出“©”. > ...

  5. redis module 学习—官网文档整理

    前言 redis在4.0版本中,推出了一个非常吸引的特性,可以通过编写插件的模式,来动态扩展redis的能力.在4.0之前,如果用户想拥有一个带TTL的INCRBY 命令,那么用户只能自己去改代码,重 ...

  6. apidoc学习(接口文档定义取代word)

    apidoc的安装,参考:https://blog.csdn.net/qq_36386771/article/details/82149848 生产文档,需要先编写一个apidoc.json对接口文档 ...

  7. 深入理解DOM节点类型第四篇——文档片段节点DocumentFragment

    × 目录 [1]特征 [2]作用 前面的话 在所有节点类型中,只有文档片段节点DocumentFragment在文档中没有对应的标记.DOM规定文档片段(document fragment)是一种“轻 ...

  8. HTML5学习之跨文档传输消息(七)

    新标准中提供了文档之间直接的消息传输API.而且不限制跨域消息传递! 发送消息使用的是Window对象的postMessage(data,targetURL)方法就可以了,但给哪个window对象发送 ...

  9. jQuery(四)、文档处理

    1 内部插入 1.1 append(content | fn) 向每个匹配的元素内部追加内容. 参数: (1) content:要追加到目标中的内容. (2) function(index, html ...

随机推荐

  1. [转]Class.forName()的作用与使用总结

    1.Class类简介: Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识.这项信息纪录了每个对象所属的类.虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类 ...

  2. Excel Open Xml中CellStyleXfs,cellStyle,cellXfs之间关系的总结

    最近这几个东东打交道了几天,总算是弄明白了,综合多个帖子,现在总结如下: 在创建stylesheet时,必须创建fonts,Fills,Borders 和cellXfs(CellFormats)四个节 ...

  3. django-TDD

    1.什么是TDD: 测试驱动开发(Test-Driven Development) 它的总体思想是在写“实现”之前先写针对实现的“测试”,由于编写测试的时候 你要思考很多的可能性能,更多的思考也就意味 ...

  4. laravel用redis保存session遇到的坑,没报错,但redis-cli就是查不到

    laravel用redis保存session遇到的坑, 配置redis存储session流程是这样的 在.evn文件中把session驱动和连接改为了redis的 如下: SESSION_DRIVER ...

  5. OOM killer(Out Of Memory killer)

    最近接连遇到两个情况就是接连进程把kill掉 第一个情况就是有一个java进程被kill了.原因是我这个服务器上海部署了一个node服务,这个node服务大家都不熟悉.所以在使用的时候没有注意内存的使 ...

  6. Android 计算文件 MD5 遇到的问题

    版本下载,做 MD5 校验,使用的 MD5 算法出现了异常,当出现以 0 开头的 MD5的时候,会把 0 给忽略掉,造成 MD5 只有 31 位,造成校验失败. 转:http://blog.csdn. ...

  7. Vue知识点超快速学习

    基础知识: vue的生命周期: beforeCreate/created.beforeMount/mounted.beforeUpdate/updated.beforeDestory/destorye ...

  8. Boost家族

    大师Yoav Freund在文章<A decision-theoretic generalization of on-line leanring and an application to bo ...

  9. Webbench是有名的网站压力测试工具

    [root@666 webbench-1.5]# yum install ctags [root@666 webbench-1.5]#make && make install inst ...

  10. Debugging the Java HotSpot VM

    Open Heart Surgery: Analyzing and Debugging the Java HotSpot VM at the OS Level https://www.youtube. ...