首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >RavenDb学习(四)处理文档相关性

RavenDb学习(四)处理文档相关性

作者头像
岑玉海
发布于 2018-03-01 07:04:57
发布于 2018-03-01 07:04:57
69100
代码可运行
举报
文章被收录于专栏:岑玉海岑玉海
运行总次数:0
代码可运行
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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);
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2014-02-01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
RavenDb学习(五)结果转换
1)Result Transformers public class Order { public DateTime OrderedAt { get; set; } public Status Status { get; set; } public string CustomerId { get; set; } public IList<OrderLine> Lines { get; set; } } //单独使用 public class OrderStat
岑玉海
2018/03/01
6190
RavenDb学习(三)静态索引
在静态索引这块,RavenDb其实的是lucene,所以里面有很多概念,其实都是lucene本身的。 1.定义静态Indexes documentStore.DatabaseCommands.PutIndex( "BlogPosts/PostsCountByTag", new IndexDefinitionBuilder<BlogPost, BlogTagPostsCount> { // The Map function: for each tag of each
岑玉海
2018/03/01
8890
RavenDB起步--客户端API(二)
会话是代码和 RavenDB 交互的主要方式。会话 API 中包含如下七个常用的高级 API :
喵叔
2022/01/27
1.2K0
RavenDb学习(八)高级特性上半部分
1、事务支持 别的关系型数据库和RavenDb一起使用 using (var transaction = new TransactionScope()) { BlogPost entity = session.Load<BlogPost>("blogs/1"); entity.Title = "Some new title"; session.SaveChanges(); // will create HTTP request session.Delete(en
岑玉海
2018/03/01
7390
RavenDB建模--常见建模方案
在 RavenDB 中对如何在应用程序中进行数据建模没有任何要求,我们可以使用任何形式进行建模,RavenDB 只关心如何构建数据,这就是我们后续几篇文章要讲解的内容。
喵叔
2022/03/22
6060
RavenDb学习(二)简单的增删查改
在上一节当中已经介绍了RavenDb的文档设计模式,这一节我们要具体讲一讲如何使用api去访问RavenDb 1.连接RavenDb var documentStore = new DocumentStore { Url = "http://myravendb.mydomain.com/" }; documentStore.Initialize(); var documentStore = new DocumentStore { ConnectionStringName = "MyRav
岑玉海
2018/03/01
1.2K0
RavenDb学习(九)高级特性下半部分
1.聚合缓存 RavenDb默认是缓存所有的请求url的,最大的缓存请求数默认是2048 documentStore.Conventions.ShouldCacheRequest = url => true; documentStore.MaxNumberOfCachedRequests = 2048; 如果开启这个选项,RavenDb直接从缓存当中读取数据,而不是从服务端。 //关闭跟踪 documentStore.Conventions.ShouldAggressiveCacheTrackChan
岑玉海
2018/03/01
8190
.NET性能优化的10个关键教训:资深工程师的实战经验
在作为高级软件工程师开发高规模.NET应用的十多年中,我亲历了众多性能挑战。有些经验来自深夜的生产事故,有些来自艰难的优化冲刺。以下是团队和我通过惨痛教训总结的十大最具影响力的性能优化实践。
郑子铭
2025/04/24
2050
.NET性能优化的10个关键教训:资深工程师的实战经验
RavenDB起步--第一个 RavenDB 程序
本篇文章将带领大家实现一个小的 RavenDB 案例程序,要求是这样的:实现一个 ToDoList 程序,可以对它进行新增、修改。下面我们开始吧!
喵叔
2022/01/24
4380
如何重构和清理 .NET 代码:编写安全且可维护的代码
在 .NET 开发中,很容易陷入编码实践,这些实践可能会悄无声息地降低应用程序的质量、安全性和可维护性。这些“无声代码剧透”可能会引入错误,导致安全漏洞,并使代码难以阅读和更新。在本文中,我们将探讨 .NET 应用程序中的不良代码示例,并逐步演示如何根据干净的代码原则重构它,包括命名约定、配置管理、SQL 注入预防和更好的结构。
郑子铭
2024/12/30
2280
如何重构和清理 .NET 代码:编写安全且可维护的代码
Hibernate_day02总结
Hibernate_day02总结 今日内容 l Hibernate持久化对象的状态 l Hibernate的一级缓存 l Hibernate操作持久化对象的方法 l Hibernate 关联关系映射 1.1 上次课内容回顾: Hibernate框架的概述. * 什么是Hibernate * 持久层的ORM框架. * ORM:对象关系映射. * 常见的持久层框架 * JPA * Hibernate * Mybatis * JdbcTemplate * Hibernate流行版本: * 3.x和4.x H
Java帮帮
2018/03/19
1.6K0
Hibernate_day02总结
Hibernate的缓存机制如何应用?
2.一级缓存应用: save()。当session对象调用save()方法保存一个对象后,该对象会被放入到session的缓存中。 get()和load()。当session对象调用get()或load()方法从数据库取出一个对象后,该对象也会被放入到session的缓存中。 使用HQL和QBC等从数据库中查询数据。
小小鱼儿小小林
2020/06/24
5200
flatMap示例
处理包含超过一个级别的流,例如Stream<String[]>、Stream<List>或者Stream<Stream>是具有挑战的。将两个级别的流划分为一个级别,例如Stream或者Stream,我们就可以很容易的处理它。
全栈程序员站长
2022/09/05
8820
Hibernate_day04总结
更多资源分享就在【Java帮帮】微信公众号与QQ空间 Hibernate_day04总结 今日内容 l Hibernate的二级缓存 1.1 上次课内容回顾: Hibernate的检索方式 * 对象导航的方式:customer.getOrders() * OID检索方式:get/load * HQL检索: * 简单查询:from Customer * 别名查询:from Customer as c * 多态查询:from java.lang.Object * 排序查询:from Customer ord
Java帮帮
2018/03/19
6810
Hibernate_day04总结
Hibernate二级缓存的使用「建议收藏」
SessionFactory 级别缓存 —- 二级缓存(进程范围)
全栈程序员站长
2022/08/31
1.4K0
Hibernate二级缓存的使用「建议收藏」
Hibernate第二天:Hibernate的一级缓存、其他的API
持久化,将内存中的一个对象持久化到数据库的过程。Hibernate框架就是用来进行持久化的框架。
AlbertYang
2020/09/08
7810
[ SSH框架 ] Hibernate框架学习之四(JPA操作)
一、JPA概述以及它和Hibernate之间的关系 1.1.Hibernate 概述   JPA Java Persistence API,是EJB3规范中负责对象持久化的应用程序编程接口(ORM接口),它定义一系列的注释。这些注释大体可分为:类级别注释、方法级别注释、字段级别注释。给实体类添加适当的注释可以在程序运行时告诉Hibernate如何将一个实体类保存到数据库中以及如何将数据以对象的形式从数据库中读取出来。   目前有两种注释方案可以确定对象与表格之间的对应关系:一种是注释实体类的属性字段(字段级
Kevin_Zhang
2018/05/22
7.2K0
[原创]Fluent NHibernate之旅(四)-- 关系(下)
最近一直忙着准备去旅行的东东,所以进度慢下来了,明天就要出发了,嘿嘿,在出发前,把多对多给写完吧。如果你第一次看这个系列,可以先看看先前几篇,了解下。 一、开篇:ISessionFactory Configuration 二、实体映射:Entity Mapping 三、继承映射:Inheritence Mapping 四、一对一映射:One-to-One Mapping 五、一对多映射:One-to-Many Mapping 场景和数据库设计 前两篇我们介绍了“一对一”和“一对多(多对一)”,或许前两种用
脑洞的蜂蜜
2018/02/02
7990
[原创]Fluent NHibernate之旅(四)-- 关系(下)
[ SSH框架 ] Hibernate框架学习之二
一、Hibernate持久化类的编写规范 1.什么是持久化类  Hibernate是持久层的ORM影射框架,专注于数据的持久化工作。所谓持久化,就是将内存中的数据永久存储到关系型数据库中。那么知道了什么是持久化,什么又是持久化类呢?其实所谓的持久化类指的是一个Java类与数据库表建立了映射关系,那么这个类称为是持寺久化类。其实可以简单的理解为持久化类就是一个Java类有了一个映射文件与数据库的表建立了关系。那么我们在编写持久化类的时候有哪些要求呢?接下来我们来看一下: 2.持久化类的编写规则(应该遵循Ja
Kevin_Zhang
2018/05/22
8980
Entity Framework 一对多关系映射
EF中关系映射也是一个很关键的内容,关系映射和属性映射一样,也是在 OnModelCreating 中配置映射。EF中的关系映射有如下三种:
喵叔
2020/09/08
1.1K0
Entity Framework 一对多关系映射
相关推荐
RavenDb学习(五)结果转换
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档