更好的 mongodb 嵌套信息数据模型

Better mongodb data model for nested information

我正在为 mango db 设计一些数据模型,我有一些类似于下面的要求 json。

Single_Collection.

{

"collegeid": 1234,
"Name": "aaaa",
 "otherinfo": 1,

"studnet":[
    {
        "stdid": 1,
        "name": "n1"
    },
    {
        "stdid": 2,
        "name": "n2"
    }
]
}

两个Collections.

  1. 大学信息

    {
    "collegeid": 1234,
    "Name": "aaaa",
     "otherinfo": 1
    }
    

学生信息collection

    {
    "collegeid": 1234,
    "stdid": 1,
    "name": "n1"
    }

    {
    "collegeid": 1234,
    "stdid": 2,
    "name": "n2"
    }

就阅读表现而言,哪种方法更好(单读 collection 或将其分开),我读得更多,比如给定学生 ID 找出大学 ID。 学生证名单会很大。

我也执行更多的学生插入操作

IMO,每个模型设计都有自己的优点和缺点,我们所说的"better way"取决于您的用例(您如何查询数据?开头需要全部数据吗?需要分页吗?等...)

让我们从您的要求开始。

您的要求

  1. 给定一个学院ID,找出该学院的学生。
  2. 给定学生证,找出他的大学证。

objects

之间的关系

很明显college & student是1:m映射,因为一所学院的学生很多,但每个学生只能在一所学院呆

我将向您展示一些不同的模型设计,并提供每个模型的优缺点。

方法 1 - 让学生融入大学

这是您提到的单个设计collection。

{
   "collegeid":1234,
   "Name":"aaaa",
   "otherinfo":1,
   "studnet":[
      {
         "stdid":1,
         "name":"n1"
      },
      {
         "stdid":2,
         "name":"n2"
      }
   ]
}

优点:

  1. 人类阅读和 front-end 显示的非常自然的模型。
  2. 在加载大学和其中的所有学生时表现良好。因为存储在引擎中的数据是连续的。引擎需要更少的 I/O 来做到这一点。

缺点:

  1. 如果一所大学的学生人数众多,文档的大小将会非常大。如果你经常add/remove/update学生,效率会很低。
  2. 没有快速实现要求 (2) 的方法。因为我们只维护college -> students 的映射,所以你必须遍历所有文档才能找出哪个college 包含指定的studentID。

方法 2 - 学生参考大学

这就是你提到的设计二Collections。它类似于 RDBMS 表,学生模型拥有其大学的参考关键点。

  1. 大学collection:
{
   "collegeid":1234,
   "Name":"aaaa",
   "otherinfo":1
}
  1. 学生collection:
{
   "collegeid":1234,
   "stdid":1,
   "name":"n1"
}
{
   "collegeid":1234,
   "stdid":2,
   "name":"n2"
}

优点:

  1. 可以达到要求(1)和(2)。请记住在 "collegeid""stdid" 字段上添加索引。
  2. 每个文档都可以保持在较小的体积,便于引擎存储数据。

缺点:

  1. 学院和学生是分开的。如果加载大学及其所有学生(需要两个查询),它将比方法 1 慢。
  2. UI.
  3. 显示前需要自行合并学院和学生

方法 3 - 大学和学生中的重复数据

这种方法看起来像是我们混合了方法 1 和方法 2。我们有两个 collections: college 将其学生嵌入自身,还有一个分离的学生 collection。因此,学生数据在 collection 中都是重复的。

  1. 大学collection:
{
   "collegeid":1234,
   "Name":"aaaa",
   "otherinfo":1,
   "studnet":[         // duplicated here!
      {
         "stdid":1,
         "name":"n1"
      },
      {
         "stdid":2,
         "name":"n2"
      }
   ]
}
  1. 学生collection:
{
   "collegeid":1234,
   "stdid":1,
   "name":"n1"
}
{
   "collegeid":1234,
   "stdid":2,
   "name":"n2"
}

优点:

  1. 您拥有方法 1 和方法 2 的所有优点。

缺点:

  1. 大学里的文件collection会长的很大
  2. 大学collection和学生collection同步的数据需要自己保管。

方法 4 - 大学(仅学生 ID)和学生中的重复数据

这是方法 3 的变体。 我们假设您的用例是:

  1. 用户可以搜索大学。
  2. 用户在搜索结果中点击了一所大学。
  3. 新的 UI 向用户显示所有学生 ID(可能在网格或列表中)。
  4. 用户点击一个学号。
  5. 系统加载指定学生的完整数据并在另一个UI.
  6. 中显示给用户

简而言之,用户一开始不需要所有学生的完整数据,他只需要学生的基本信息(例如学号)。如果用户接受这样的场景,你可以有以下模型:

  1. 大学collection:
{
   "collegeid":1234,
   "Name":"aaaa",
   "otherinfo":1,
   "studnetIds":[1, 2]  // only student IDs are duplicated
}
  1. 学生collection:
{
   "collegeid":1234,
   "stdid":1,
   "name":"n1"
}
{
   "collegeid":1234,
   "stdid":2,
   "name":"n2"
}

学院只有学生网ID。这是与方法 3 相比的区别。

优点:

  1. 可以达到要求(1)和(2)。
  2. 您无需担心大学文件变得庞大。因为它只拥有学生证。
  3. 如果用户接受上述情况,这将是一个更好的设计,平衡 performance/complex/data 大小。

缺点:

  1. 适合特定的用例,如果以后需求变化,会破坏场景,这个模型不好。

总结

  1. 你应该很清楚你的用例。
  2. 根据用例,比较方法,看看您是否可以接受优缺点。
  3. 负载测试很重要!