I have problem to retrieve information between two collections. The first collection stores employees information:
{
"_id" : ObjectId("4f9643967f8b9a3f0a00005a"),
"birth_date" : "1963-09-09",
"departments" : [
{
"departments_id" : ObjectId("4f9643957f8b9a3f0a000007"),
"from_date" : "1990-01-03",
"to_date" : "1990-01-15"
}
],
"first_name" : "Parviz",
"gender" : "M",
"hire_date" : "1990-01-03",
"last_name" : "Lortz",
}
the second one the departments information
{
"_id" : ObjectId("4f9643957f8b9a3f0a000004"),
"dept_name" : "Marketing",
"managers" : [
{
"employees_id" : ObjectId("4f96439b7f8b9a3f0a0186a9"),
"from_date" : "1985-01-01",
"to_date" : "1991-10-01"
},
{
"employees_id" : ObjectId("4f96439b7f8b9a3f0a0186aa"),
"from_date" : "1991-10-01",
"to_date" : "9999-01-01"
}
]
}
I try to find: All departments for a given employee.
I tried something like:
employees = db.employees.find({_id:ObjectId("some_id")});
db.departments.find({_id:{$in:...}});
But I don't know how I can explain $in department_id of all departments from var employees.
In MongoDB's document model, a 1:N relationship data can be stored within a collection; this is a de-normalized form of data. The related data is stored together and can be accessed (and updated) together. The comments are stored as an array; an array of comment objects.
In MongoDB, you can access the fields of nested/embedded documents of the collection using dot notation and when you are using dot notation, then the field and the nested field must be inside the quotation marks.
The $elemMatch operator matches documents that contain an array field with at least one element that matches all the specified query criteria. If you specify only a single <query> condition in the $elemMatch expression, and are not using the $not or $ne operators inside of $elemMatch , $elemMatch can be omitted.
There is an easy way to do that in Mongo 3.2, at least in just a single operation:
const employees = db.employees.find(); // query the employees collection
db.departments.find({
managers: {
$elemMatch: {
employees_id: {
$in: employees.map(e => e._id)
}
}
}
});
The $elemMatch
modifier (see ref) helps query against an array-like value of an object property.
This can not be done with a simple query. You will have to loop over employees.departments and for each iteration add its departments_id to an array. This array you then can use in your second line. This is something best done in your language of choice.
In order to make this easier, you'll have to change your schema. One option is to store the department information in the employee record, but in your case you'd be duplicating a lot of data.
I would instead suggest to have each department contain a list with employee IDs and dates instead like this:
{
"_id" : ObjectId("4f9643957f8b9a3f0a000004"),
"dept_name" : "Marketing",
"managers" : [
]
"employees" : [
{
"employee_id" : ObjectId("4f9643967f8b9a3f0a00005a"),
"from_date" : "1990-01-03",
"to_date" : "1990-01-15"
}
]
}
In that case, you can then simply run:
db.departments.find( { "employees.employee_id": ObjectId("some_id") } );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With