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

时间:2019-03-18 17:22:02

标签: mongodb mongodb-query data-modeling

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

Single_Collection。

{

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

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

两个收藏集。

  1. 大学信息

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

学生信息收集

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

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

这是阅读表现的最佳方式(可以单独收集或分开阅读),我可以阅读更多的书,例如给定的学生证可以找到大学证。 学生证列表会很大。

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

1 个答案:

答案 0 :(得分:1)

IMO,每种模型设计都有其优点和缺点,我们所说的“更好的方式”取决于您的用例(如何查询数据?您是否需要所有数据?开始吗?是否需要分页?等...)

让我们从您的要求开始。

您的要求

  1. 给出大学ID,找出这所大学的学生。
  2. 给出学生证,找出他的大学证。

对象之间的关系

显然,大学与学生是 1:m 映射,因为在一所大学中有很多学生,但每个学生只能留在一所大学。

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

方法1-让学生进入大学

这是您提到的单个收藏集的设计。

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

优点:

  1. 非常自然的模型,可供人类阅读和前端显示。
  2. 在加载学院和其中的所有学生时表现良好。因为存储在引擎中的数据是连续的。引擎需要更少的I / O。

缺点:

  1. 如果您在一所大学中有大量学生,那么文档的大小将非常大。如果您经常添加/删除/更新学生,这将是低效率的。
  2. 没有快速的方法可以达到要求(2)。由于我们只维护来自大专院校->学生的映射,因此您必须浏览所有文档以找出哪个大学包含指定的StudentID。

方法2-学生参考了大学

这是您提到的两个集合的设计。它类似于RDBMS表,学生模型拥有其大学的参考关键点。

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

优点:

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

缺点:

  1. 学院和学生是分开的。如果加载一所大学及其所有学生,这将比方法1慢(需要两个查询)。
  2. 在UI中显示之前,您需要将大学和学生自己合并在一起。

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

这种方法看起来像是将方法1和方法2混合在一起。我们有两个馆藏:大学将把学生嵌入其中,还有一个单独的学生馆藏。因此,两个集合中的学生数据都是重复的。

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

优点:

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

缺点:

  1. 大学收藏中的文档将变得很大。
  2. 您必须自己同步保留大学收藏和学生收藏中的数据。

方法4-高校和学生的数据重复(仅限学生ID)

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

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

简而言之,用户一开始并不需要所有学生的全部数据,他只需要学生的基本信息(例如学生ID)。如果用户接受这种情况,则可以使用以下模型:

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

学院中只有学生ID。与方法3相比,这是不同的。

优点:

  1. 可以达到要求(1)和(2)。
  2. 您不必担心大学文件的规模会很大。由于它仅拥有学生证。
  3. 如果用户接受上述情况,这将是性能/复杂性/数据大小之间更好的平衡点。

缺点:

  1. 适合于指定用例的情况,如果将来更改需求,将破坏该方案,并且此模型不好。

摘要

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