我已经使用微服务一段时间了,总是使用关系数据库。我正在查看 MongoDb,但不确定如何处理涉及不同微服务的实体关系。下面是一个例子:
public class Employee implements Serializable {
private String id;
...
}
public class Department implements Serializable {
private String id;
private String desc;
private List<Employee> employees = new ArrayList<>();
...
}
这两个实体由两个不同的微服务管理,一对多关系由 Department
实体管理。到现在为止还挺好。使用关系数据库(作为一种可选关系,并且一名员工可能属于多个部门),我会将其映射到
Departments
微服务中,其中一张表包含两个字段: employee_id
和 department_id
。当客户端调用 getDepartmentWithEmployees(depId)
时,该微服务将读取表并从 Employees
微服务中获取合适的员工。但是,在 MongoDb 数据库中,据我所知,当我存储
Department
对象时,它会存储所有关联的 Employee
。这不是复制信息吗?有没有办法,也许,MongoDb 不存储有关员工的所有信息,而只存储他们的 id?或者还有其他答案?我很确定这是一个非常基本的问题,但我对所有这些东西都很陌生。
提前致谢。
最佳答案
But, in a MongoDB database, as far as I know, when I store a Department object it stores all associated Employees. Is not that duplicating the information?
首先,上面的说法是不正确的。从 MongoDB 的角度来看,作为 BSON 提供的任何内容都按原样存储。如果您为员工提供部门,那么是的,它应该。您可以在创建部门后应用部分更新...(例如使用
$set
运算符)。但是,我认为您的问题的范围比这更广泛。恕我直言,为数据库中的每个文档/表创建 纳米服务 不是一个好方法。特别是当服务只负责基本的 CRUD 操作时。您应该首先定义您的有界上下文、聚合根等……简而言之,在将业务需求映射到域对象之前不要尝试设计表格。我想说的是使用 DDD 原则:)
这些是我目前发现的策略。在设计微服务时,您还应该考虑每种策略的利弊。 (见底部引用。)
将关系数据库映射到 NoSQL 的一般原则
1:1 关系
1:1 关系可以通过两种方式映射;
表格:
// Employee document
{
"id": 123,
"Name":"John Doe"
}
// Address document
{
"City":"Ankara",
"Street":"Genclik Street",
"Nr":10
}
示例:嵌入 (1:1)
{
"id": 123,
"Name":"John Doe",
"Address": {
"City":"Ankara",
"Street":"Genclik Street",
"Nr":10
}
}
示例:使用外键链接 (1:1){
"id": 763541685, // link this
"Name":"John Doe"
}
带有文件 key 的地址;{
"employee_id": 763541685,
"City":"Ankara",
"Street":"Genclik street",
"Nr":10
}
1:M 关系
最初的:
// Department collection
{
"id": 1,
"deparment_name": "Software",
"department_location": "Amsterdam"
}
/// Employee collection
[
{
"employee_id": 46515,
"employee_name": "John Doe"
},
{
"employee_id": 81584,
"employee_name": "John Wick"
}
]
示例:嵌入 (1:M)警告:
{
"id": 1,
"deparment_name": "Software",
"department_location": "Amsterdam",
"employess": [
{
"employee_id": 46515,
"employee_name": "John Doe"
},
{
"employee_id": 81584,
"employee_name": "John Wick"
}
]
}
示例:链接 (1:M)我们可以从员工文档中链接部门 ID。
Retrieve all employees that are belong to department X.
这个查询需要很多读操作! [
{
"employee_id": 46515,
"employee_name": "John Doe",
"department_id": 1
},
{
"employee_id": 81584,
"employee_name": "John Wick",
"department_id": 1
}
]
示例:分桶策略(混合 1:M)我们将员工分成多个桶,每个桶最多 100 名员工。
{
"id":1,
"Page":1,
"Count":100,
"Employees":[
{
"employee_id": 46515,
"employee_name": "John Doe"
},
{
"employee_id": 81584,
"employee_name": "John Wick"
}
]
}
N:M 关系
To choose Two Way Embedding or One Way Embedding, the user must establish the maximum size of N and the size of M.
For example; if N is a maximum 3 categories for a book and M is a maximum of 5,000,000 books in a category you should pick One Way Embedding.
If N is a maximum 3 and M is a maximum of 5 then Two Way Embedding might work well. schema basics
示例:双向引用 (N:M)
在双向嵌入中,我们将在作者文档的 book 字段下包含 Book 外键。
作者合集
[
{
"id":1,
"Name":"John Doe",
"Books":[ 1, 2 ]
},{
"id":2,
"Name": "John Wick",
"Books": [ 2 ]
}
]
藏书:[
{
"id": 1,
"title": "Brave New World",
"authors": [ 1 ]
},{
"id":2,
"title": "Dune",
"authors": [ 1, 2 ]
}
]
示例:单向引用 (N:M)示例书籍和类别:这种情况是几本书属于几个类别,但几个类别可以有很多本书。
类别
[
{
"id": 1,
"category_name": "Brave New World"
},
{
"id": 2,
"category_name": "Dune"
}
]
带有 Book
外键的 Categories
文档示例[
{
"id": 1,
"title": "Brave New World",
"categories": [ 1, 2 ],
"authors": [ 1 ]
},
{
"id": 2,
"title": "Dune",
"categories": [ 1],
"authors": [ 1, 2 ]
}
]
引用关于java - 在微服务架构中管理与 MongoDb 的关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66674061/