I've been working with microservices for some time now, always with relational databases. I am looking at MongoDb and I am not sure how to handle entity relationships involving different microservices. Here goes an example:
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<>();
...
}
These two entities are managed by two different microservices, with a one-to-many relationship managed by the Department
entity. So far, so good.
With a relational database (being an optional relationship and with the possibility of one employee belonging to several departments) I'd map this in the Departments
microservice with one table containing two fields: employee_id
and department_id
. When the client calls getDepartmentWithEmployees(depId)
this microservice will read the table and obtain the proper employees from the Employees
microservice.
But, in a MongoDb database, as far as I know, when I store a Department
object it stores all associated Employee
s. Is not that duplicating the information? Is there a way, maybe, where MongoDb don't store all info about the employees but just their id? Or there is another answer?
I am pretty sure this is a very basic question, but I am new to all this stuff.
Thanks in advance.
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?
First of all, the statement above is not correct. From the MongoDB's perspective, whatever is provided as BSON is stored as it is. If you provide employees with the department then yes, it should. You can apply partial updates after creating the department... (eg using $set
operator). But, I think the scope of your question is broader than this.
IMHO, creating nano-services for each document/table in the database is not a good approach. Especially, when the services only responsible for basic CRUD operation. You should first define your bounded contexts, aggragate roots and etc... In short, do not try to design tables before mapping business requirements to domain objects. What I'm trying to say is use DDD principles:)
These are the strategies that I found so far. When designing microservices you should also consider pros and cons of each strategy. (See bottom for references.)
The 1:1 relation can be mapped in two ways;
Tables:
// 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"
}
Address with document key;
{
"employee_id": 763541685,
"City":"Ankara",
"Street":"Genclik street",
"Nr":10
}
Initial:
// 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"
}
]
Warning:
{
"id": 1,
"deparment_name": "Software",
"department_location": "Amsterdam",
"employess": [
{
"employee_id": 46515,
"employee_name": "John Doe"
},
{
"employee_id": 81584,
"employee_name": "John Wick"
}
]
}
We can link department_id from employee document.
Retrieve all employees that are belong to department X.
This query will need a lot of read operations![
{
"employee_id": 46515,
"employee_name": "John Doe",
"department_id": 1
},
{
"employee_id": 81584,
"employee_name": "John Wick",
"department_id": 1
}
]
We'll split the employees into buckets with maximum of 100 employees in each bucket.
{
"id":1,
"Page":1,
"Count":100,
"Employees":[
{
"employee_id": 46515,
"employee_name": "John Doe"
},
{
"employee_id": 81584,
"employee_name": "John Wick"
}
]
}
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
In Two Way Embedding we will include the Book foreign keys under the book field in the author document.
Author collection
[
{
"id":1,
"Name":"John Doe",
"Books":[ 1, 2 ]
},{
"id":2,
"Name": "John Wick",
"Books": [ 2 ]
}
]
Book collection:
[
{
"id": 1,
"title": "Brave New World",
"authors": [ 1 ]
},{
"id":2,
"title": "Dune",
"authors": [ 1, 2 ]
}
]
Example Books and Categories: The case is that several books belong to a few categories but a couple categories can have many books.
Catergory
[
{
"id": 1,
"category_name": "Brave New World"
},
{
"id": 2,
"category_name": "Dune"
}
]
An example of a Book
document with foreign keys for Categories
[
{
"id": 1,
"title": "Brave New World",
"categories": [ 1, 2 ],
"authors": [ 1 ]
},
{
"id": 2,
"title": "Dune",
"categories": [ 1],
"authors": [ 1, 2 ]
}
]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.