【问题标题】:Thinking NoSql on reference data在参考数据上思考 NoSql
【发布时间】:2026-01-09 05:20:04
【问题描述】:

我正在尝试 NoSql,但在探索过程中,我无法思考如何处理参考数据。 (我习惯于传统的数据库,表格数据库)说,我有一个有学生和要求的学校实体。现在,学生可以注册到学校并可以在以后遵守要求。因此,学校会寻找一名学生并检查他遵守了哪些要求。

在传统数据库上,我会做类似的事情。

+---------+  +---------------+ +--------------------+ +---------+
| School  |  | Requirement   | | StudentRequirement | | Student |
+---------+  +---------------+ +--------------------+ +---------+
| Id (PK) |  | Id (PK)       | | Id (PK)            | | Id (PK) |
| Name    |  | Name          | | StudentId (FK)     | | Name    |
+---------+  | SchoolId (FK) | | RequirementId (FK) | +---------+
             +---------------+ | HasComply          |
                               +--------------------+

我将创建 4 个实体,RequirementStudent 具有多对多关系。所以无论我是编辑还是删除Requirement,我都可以只看中间表。

流程类似于:

// EnrollStudentToASchool
// AssignAllRequirementsToNewStudent

然后在我的代码中的某个地方,如果创建了新需求

// IfNewRequirement
// AddNewRequirementToStudent

现在,在 NoSql 中,就我而言,我使用的是 mongodb,一种 doc 类型的数据存储。我在某处读到数据应该是内联的。比如:

{
  Id: 1,
  School: 'Top1 Foo School',
  Requirements: 
  [
    { Id: 1, Name: 'Req1' },
    { Id: 2, Name: 'Req2' }
  ],
  Students: 
  [
    { 
      Id: 1, 
      Name: 'Student1',
      Requirements:
      [
        { Id: 1, Name: 'Req1', HasComply: false },
        { Id: 2, Name: 'Req2', HasComply: true },
      ]
    }
  ]
},
{
  Id: 2,
  School: 'Top1 Bar School',
  Requirements: [],
  Students: []
}

我的文档的根是School,与上面的流程相同:

// EnrollStudentToASchool
// AssignAllRequirementsToNewStudent
// IfNewRequirement
// AddNewRequirementToStudent

但如果学校决定编辑Requirement 的名称或删除Requirement

应该怎么做?我应该循环我所有的学生并编辑/删除要求吗?或者我做错了。

请指教。

【问题讨论】:

    标签: mongodb nosql


    【解决方案1】:

    这是一个不错的用例。

    您的示例提出了从 sql 转换为 noSql 的大部分相关优点和缺点。

    首先请查看建议的系列设计:

    我们有两个系列:schoolstudent 为什么会这样?我们需要考虑 bson 文档的大小限制(16MB),如果我们有足够多的学生可以超过这个大小。

    那么为什么我们要在每个学生记录中重复数据呢?如果我们想要学生的详细信息,我们不需要去学校(没有额外的往返)。

    我们在学校有一系列要求(一种大师),然后每个学生都有自己的结果。

    添加/删除此类数据需要通过所有学生和学校进行迭代。

    简而言之 - 日常显示操作不连接 => 效率,但更新会产生比 sql 更多的负载。

    欢迎任何 cmets!

    【讨论】:

    • 如果我理解正确,请告诉我。您创建了 2 个集合,即 schoolstudent。您将学校详细信息嵌入到每个学生中,因此无需额外往返。现在,如果从学校添加/更新/删除了 requirement,我们需要迭代所有学生和学校记录。正确的?顺便说一句,非常感谢您为视觉关系付出的努力
    • 我还注意到在视觉表示上,您将requirements 嵌入到student。不需要额外的往返吗?如果您要在 C# 类上表示它。 public class Student { public int Id { get; set; } public string Name { get; set; } public string SchoolName { get; set; } public ICollection<Requirements> Requirements { get; set; } }这不是设计的味道吗?还是事先有某种配置或映射?
    • 学校要求没有“遵守”,嵌入的是学校名称和 id - 不是所有对象
    • 我明白了。我只是在想,如果我将School 的一些属性放到StudentSchool.RequirementsStudent.Requirements,这可能是代码异味或类似的东西?
    • 将学校与需求一起嵌入会更容易一些,但需要在学校和学生中进行更新。有代码气味 - 这是 noSql :-)