C# DocumentDB中每个集合有一个或多个实体

C# DocumentDB中每个集合有一个或多个实体,c#,azure,azure-cosmosdb,C#,Azure,Azure Cosmosdb,文档数据库中每个集合是否应该有一个实体 假设我在下图中有外键关系: 我应该为员工和公司创建两个集合吗。或者我应该将它们存储到单个集合中 我了解到,在documentdb中,存储过程的范围触发器等都在一个集合中。因此,通过将不同的实体拆分为单独的集合,我释放了开箱即用的功能 因此,将这两个类作为单个实体转储不是更好吗,如下所示: { "Id": 1001, "Industry": "Software", "Employees": [ { "Id": 10011,

文档数据库中每个集合是否应该有一个实体

假设我在下图中有外键关系:

我应该为员工和公司创建两个集合吗。或者我应该将它们存储到单个集合中

我了解到,在documentdb中,存储过程的范围触发器等都在一个集合中。因此,通过将不同的实体拆分为单独的集合,我释放了开箱即用的功能

因此,将这两个类作为单个实体转储不是更好吗,如下所示:

{
  "Id": 1001,
  "Industry": "Software",
  "Employees": [
    {
      "Id": 10011,
      "Name": "John Doe",
      "CompanyId": 1001
    },
    {
      "Id": 10012,
      "Name": "Jane Doe",
      "CompanyId": 1001
    }
  ]
}

在DocumentDB中实现相关实体的标准做法是什么?

您的问题有点主观,因为您要求的是实体设计,因此没有一个正确的答案

但是:从更客观的角度来看:没有什么可以阻止您在一个集合中拥有多个实体类型(例如,在您的情况下,
公司
文档类型和
员工
文档类型)

您需要为自己包含某种类型的提示(可能是
type
属性),以帮助在运行查询时区分这两种类型。但是,通过在同一个集合中同时使用这两种类型,您现在可以在一个集合范围内工作。关于
类型
属性:由于默认情况下DocumentDB索引所有属性,因此
类型
属性很容易集成到查询中


编辑删除了每个容量单位3个集合的部分,因为当DocumentDB从预览转移到生产时,该安排被删除。

通常最好为每个集合存储多个实体类型。是否将实体类型存储在单个文档中需要更多的考虑

正如David提到的,如何对数据建模有点主观

在一个集合中存储多个实体类型

首先。。。让我们谈谈在集合中存储多个实体。DocumentDB集合不是表。集合不强制模式;换句话说,您可以在同一个集合中存储具有不同模式的不同类型的文档。只需向文档中添加类型属性,即可跟踪不同类型的实体

您应该将集合视为执行查询和事务的分区和边界单元。因此,在同一个集合中存储不同实体类型的一个巨大好处是,您可以通过存储过程立即获得事务支持

在文档中存储多个实体类型

是否在一个文档中存储多个实体类型需要更多的考虑。这通常被称为反规范化(通过在单个文档中嵌入数据来捕获数据之间的关系)和规范化(通过创建到其他文档的弱链接来捕获数据之间的关系)

通常,反规范化提供了更好的读取性能

应用程序可能需要发出较少的查询和更新来完成常见操作

通常,在以下情况下使用非规范化数据模型:

  • 在实体之间具有“包含”关系
  • 实体之间有一对几个关系
  • 非规范化数据很少更改
  • 如果没有绑定,非规范化数据将不会增长
  • 非规范化数据是文档中数据的一部分
非规范化数据模型的示例:

{
  "Id": 1001,
  "Type": "Company",
  "Industry": "Software",
  "Employees": [
    {
      "Id": 10011,
      "Type": "Employee",
      "Name": "John Doe"
    },
    {
      "Id": 10012,
      "Type": "Employee",
      "Name": "Jane Doe"
    }
  ]
}
{
  "Id": 1001,
  "Type": "Company",
  "Industry": "Software"
}

{
  "Id": 10011,
  "Type": "Employee",
  "Name": "John Doe",
  "CompanyId": 1001
}

{
  "Id": 10012,
  "Type": "Employee",
  "Name": "Jane Doe",
  "CompanyId": 1001
}
通常,规范化提供了更好的写入性能

提供比反规范化更大的灵活性

客户端应用程序必须发出后续查询以解析引用。换句话说,规范化数据模型可能需要更多到服务器的往返

通常,使用规范化数据模型:

  • 当反规范化会导致数据重复,但不会提供足够的读取性能优势来抵消重复的影响时
  • 表示一对多关系
  • 表示多对多关系
  • 相关数据经常更改
规范化数据模型的示例:

{
  "Id": 1001,
  "Type": "Company",
  "Industry": "Software",
  "Employees": [
    {
      "Id": 10011,
      "Type": "Employee",
      "Name": "John Doe"
    },
    {
      "Id": 10012,
      "Type": "Employee",
      "Name": "Jane Doe"
    }
  ]
}
{
  "Id": 1001,
  "Type": "Company",
  "Industry": "Software"
}

{
  "Id": 10011,
  "Type": "Employee",
  "Name": "John Doe",
  "CompanyId": 1001
}

{
  "Id": 10012,
  "Type": "Employee",
  "Name": "Jane Doe",
  "CompanyId": 1001
}
混合方法

在正常化和非正常化之间进行选择不必是黑白选择。我经常发现,一个成功的设计模式是一种混合方法,在这种方法中,您可以选择规范化一部分对象的字段,然后对其他字段进行反规范化

换句话说,您可以选择对频繁读取的稳定(或不可变)属性进行非规范化,以减少后续查询的需要,而对频繁写入/变异字段进行规范化,以减少分散写入的需要

混合方法的示例:

// Author documents:
[{
  "id": 1,
  "firstName": "Thomas",
  "lastName": "Andersen",
  "countOfBooks": 3,
  "books": [1, 2, 3],
  "images": [{
    "thumbnail": "http://....png"
  }, {
    "profile": "http://....png"
  }, {
    "large": "http://....png"
  }]
}, {
  "id": 2,
  "firstName": "William",
  "lastName": "Wakefield",
  "countOfBooks": 1,
  "books": [1, 4, 5],
  "images": [{
    "thumbnail": "http://....png"
  }]
}]

// Book documents:
[{
  "id": 1,
  "name": "DocumentDB 101",
  "authors": [{
    "id": 1,
    "name": "Thomas Andersen",
    "thumbnailUrl": "http://....png"
  }, {
    "id": 2,
    "name": "William Wakefield",
    "thumbnailUrl": "http://....png"
  }]
}, {
  "id": 2,
  "name": "DocumentDB for RDBMS Users",
  "authors": [{
    "id": 1,
    "name": "Thomas Andersen",
    "thumbnailUrl": "http://....png"
  }, ]
}]

在过去5年中,Cosmos DB中发生了许多变化,影响数据结构设计的最重要变化之一是创建许多容器并在所有容器之间共享RU的可能性

在同一容器中组合多个实体类型(集合的新名称)仍然可以。然而,在2020年,将每种实体类型放在单独的容器中也可以

当然,这取决于您的应用程序的需要,一个非常重要的考虑因素是您打算如何阅读这些信息。但是,以下是您可以考虑的一般数据结构和方法:

  • 将每个实体保存在各自的容器中
  • 包含具有实体名称的属性
  • 选择分区键的方式应确保一个分区中的数据不会超过10GB
  • 确定由于呼叫量大而需要最佳性能的读取
  • 关键在于:将数据复制到针对预期读取而优化的容器中
  • 对于要优化的读取,请将数据复制到新容器中