【问题标题】:Many-to-one relationship in MongoDBMongoDB中的多对一关系
【发布时间】:2019-08-23 19:28:14
【问题描述】:

我是 MongoDB 和 NoSQL 数据库的新手,我正在尝试学习每个人在谈到 NoSQL 时都会提到的不同类型的思维。

我有一个典型的多对一关系情况。请不要告诉我 MongoDB 不是关系数据库,因为我已经知道了。关键是 - 现实以某种方式运作,我需要让我的应用程序反映它。现实世界充满了关系,如果您的答案是“为您的案例选择不同的数据库”,那么我认为 MongoDB 团队可以关闭他们的业务,因为他们的产品在这种情况下将完全没用。

让我们假设典型的员工/部门关系。 Employee 与单个Department 相关联。 部门可以有零个或多个员工

让我们假设超级简单的模型:

public class Department {

    private String name;

   // something like...
   private List<Employee> employees;

}

public class Employee {

    private String name;

   // something like...
   private Department department;

}

现在在我的 REST API 中,我需要一些非常基本的功能:

  • 获取所有部门的列表
  • 获取所有员工的列表,但必须包含每个员工的部门名称
  • 获取选定部门的员工列表

那么您将如何使用 MongoDB 解决这个问题?我也在使用 Spring Boot 和 Spring Data,但我认为这并不重要。

我遇到过不同的方法,但对我来说似乎都很糟糕。将部门嵌入员工内部将无法获取所有部门或单个部门的员工的列表。将员工嵌入部门将无法获取所有员工的列表。使用 @DbRef 将模拟关系,但是如何在不为每个员工调用 REST API 的情况下获取包括部门名称在内的员工列表?

我最近阅读了很多教程、手册和 StackOverflow 讨论,但我没有找到可以接受的答案。这么超简单的问题,MongoDB真的有可能解决不了吗?这甚至不是一个问题,而是一个标准——我们周围世界的普遍情况。

谢谢

【问题讨论】:

  • “这么超级简单的问题,MongoDB真的有可能解决不了吗?” - MongoDB 是关于文档,而不是具有关系的实体。最简单的方法是为您的“获取所有部门的列表”用例创建一个包含部门的集合,并为您的第二个和第三个用例创建一个包含所有员工的包含其部门 ID 和/或名称的集合。如果您更关心一致性而不是运行时间,则员工可能只包含部门的 ID,但您必须访问每个员工的“部门”集合以加载其部门名称。
  • 我认为在现实世界中甚至不存在这样的情况,在这种情况下,实体之间没有任何关系。如果 MongoDB 真的建立在这样的假设之上,那么 OMG :-)
  • 您能否澄清一下“访问“部门”集合以供每个员工加载其部门名称”?我的意思是 - 我如何在 Java Spring 中实现它?
  • 关系可以用冗余代替,这是MongoDB的立场。关于您的问题:我手动查询了 MongoDB,因此在加载所有员工后,您必须将 MongoDB 文档映射到您自己的数据模型中,在其中创建 Employee 对象,您必须加载适当的 Department(按 ID 过滤)部门集合。我不知道 Spring Data 能用 MongoDB 做什么。
  • 谢谢,最后我设法实现了。对这种方法不太满意,但至少它有效。

标签: spring mongodb spring-data-mongodb


【解决方案1】:

也许您可以在您的 Employee 文档中使用一个简单的departmentId(带有该部门的 Mongo ID 的值)?

这样您就可以避免嵌入文档并且您的用例可以工作:

  1. 所有部门案例只是部门集合中的查找所有内容。
  2. 所有员工都是员工集合中的全部查找对象,然后在您的服务器中,您需要为员工中存在的所有不同部门 ID 调用部门集合。
  3. 所选部门案例的所有员工都是员工集合中的按部门 ID 查找。

这会以可接受的方式为您工作吗?

【讨论】:

  • 如果我理解正确,那么您建议创建一个引用(在 Spring Data 中它是使用 @DbRef 完成的)。那么你如何处理第二个用例呢?你能附上Java代码吗?
  • 我不是建议使用 DbRef。我建议一个包含 Mongo id 的简单字符串属性。然后,在您完成所有查询后,由您在另一个应用程序层中用完整的部门文档填充您的响应对象。
  • 好的,谢谢。我会试一试。您能否建议如何在 Java Spring 中准确实现这一点?
  • 鉴于您使用 Spring 数据,您可能会有一个 DepartmentRepository 和一个 EmployeeRepository。您将不得不协调对他们两个的呼叫。首先,您可以在 EmployeeRepository 中使用 findAll(),然后根据从 Employee 对象中获得的部门 ID,您可以使用 DepartmentRepository 的 findAllById() 方法。然后,您可以根据这两个结果创建您的 API 响应。
  • @lot:你完全正确! MongoDB 的优势在于处理、搜索、过滤自包含文档,并且绝对不是模拟关系数据库。例如。在过去的一个项目中,与自制的内存缓存相比,我们使用 MongoDB 作为一种可过滤的持久缓存。
猜你喜欢
  • 2016-01-17
  • 2014-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-02
  • 2020-06-12
  • 2020-12-05
  • 2015-10-25
相关资源
最近更新 更多