我使用微服务已经有一段时间了,总是使用关系数据库。我正在查看 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?或者还有其他答案?
我很确定这是一个非常基本的问题,但我对所有这些东西都不熟悉。
提前致谢。
答案 0 :(得分:3)
但是,在 MongoDB 数据库中,据我所知,当我存储 Department 对象时,它会存储所有关联的员工。这不是复制信息吗?
首先,上面的说法是不正确的。从 MongoDB 的角度来看,作为 BSON 提供的任何内容都按原样存储。如果您为员工提供部门,那么是的,它应该。您可以在创建部门后应用部分更新...(例如使用 $set
运算符)。但是,我认为您的问题的范围比这更广泛。
恕我直言,为数据库中的每个文档/表创建纳米服务并不是一个好方法。特别是当服务只负责基本的 CRUD 操作时。您应该首先定义您的有界上下文、聚合根等……简而言之,在将业务需求映射到域对象之前不要尝试设计表格。我想说的是使用 DDD 原则:)
这些是我目前发现的策略。在设计微服务时,您还应该考虑每种策略的利弊。 (见底部参考。)
1:1 关系可以通过两种方式映射;
表格:
// Employee document
{
"id": 123,
"Name":"John Doe"
}
// Address document
{
"City":"Ankara",
"Street":"Genclik Street",
"Nr":10
}
{
"id": 123,
"Name":"John Doe",
"Address": {
"City":"Ankara",
"Street":"Genclik Street",
"Nr":10
}
}
{
"id": 763541685, // link this
"Name":"John Doe"
}
带有文档密钥的地址;
{
"employee_id": 763541685,
"City":"Ankara",
"Street":"Genclik street",
"Nr":10
}
初始:
// 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"
}
]
警告:
{
"id": 1,
"deparment_name": "Software",
"department_location": "Amsterdam",
"employess": [
{
"employee_id": 46515,
"employee_name": "John Doe"
},
{
"employee_id": 81584,
"employee_name": "John Wick"
}
]
}
我们可以从员工文档中链接department_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
}
]
我们会将员工分成多个桶,每个桶最多 100 名员工。
{
"id":1,
"Page":1,
"Count":100,
"Employees":[
{
"employee_id": 46515,
"employee_name": "John Doe"
},
{
"employee_id": 81584,
"employee_name": "John Wick"
}
]
}
要选择双向嵌入或单向嵌入,用户必须确定最大大小 N 和大小 M。
例如;如果 N 是一本书最多 3 个类别,而 M 是一个类别中最多 5,000,000 本书,您应该选择单向嵌入。
如果 N 最大为 3,M 最大为 5,那么双向嵌入可能会很好地工作。 schema basics
在双向嵌入中,我们将在作者文档的 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 ]
}
]
示例书籍和类别:这种情况是几本书属于几个类别,但几个类别可以包含许多书籍。
类别
[
{
"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 ]
}
]