I am running into a scenario where I am asking myself do I need to put each entity (a Classroom has many students) into separate Meteor.collection object or rather embed an array of students inside the classroom object and have one Meteor.collection Classroom object.
My instinct tells me to put Classroom and Students in their own Meteor.collections but I am not sure how to establish a one to many relationship between the two Meteor collection objects.
What if there are many more traditional one-to-many, many-to-many relationships translate into Meteor way of doing things?
My question arises from the fact that .aggregate() is not supported, and realizing that it's impossible without doing a recursive loop to grab nested and embedded documents, inside a parent document in which Meteor collection exists (ex. Classroom).
Collections are Meteor's way of storing persistent data. The special thing about collections in Meteor is that they can be accessed from both the server and the client, making it easy to write view logic without having to write a lot of server code.
As we know that in the mongo shell, documents are represented using curly braces ( {} ) and inside these curly braces we have field-value pairs. Now inside these fields, we can embed another document using curly braces {} and this document may contain field-value pairs or another sub-document.
An embedded document is when one document (often a structured text file, or a binary, or anything else) is embedded within another. (This discussion assumes that the result is a linear sequence of bytes/characters--use of more advanced filing systems is beyond the scope of this discussion).
An embedded, or nested, MongoDB Document is a normal document that's nested inside another document within a MongoDB collection. Embedded documents are particularly useful when a one-to-many relationship exists between documents.
Most of the time it is useful to put separate object types into separate collections.
Let's say we have a one to many relationship:
Classrooms.insert({
_id: "sdf8ad8asdj2jef",
name: "test classroom"
});
Students.insert({
_id: "lof8gzanasd9a7j2n",
name: "John"
classroomId: "sdf8ad8asdj2jef"
});
Get all Students in classroom sdf8ad8asdj2jef
:
Students.find({classroomId: "sdf8ad8asdj2jef"});
Get the classroom with student lof8gzanasd9a7j2n
:
var student = Studtents.findOne("lof8gzanasd9a7j2n");
var classroom = Classrooms.find(student.classroomId);
Putting the objects into separate collections is especially useful when you are going to use Meteor.publish() and Meteor.subscribe(). Meteor.publish() is pretty handy when you want to publish only data to the client that is really relevant to the user.
The following publishes only students who are in the room with the given classroomId
.
(So the client doesn't have to download all student objects from the server database. Only those who are relevant.)
Meteor.publish("students", function (classroomId) {
return Students.find({classroomId: classroomId});
});
Many to many relationships are also not that complicated:
Classrooms.insert({
_id: "sdf8ad8asdj2jef",
name: "test classroom"
studentIds: ["lof8gzanasd9a7j2n"]
});
Students.insert({
_id: "lof8gzanasd9a7j2n",
name: "John"
classroomIds: ["sdf8ad8asdj2jef"]
});
Get all students in classroom sdf8ad8asdj2jef
:
Students.find({classroomIds: "sdf8ad8asdj2jef"});
Get all classrooms with student lof8gzanasd9a7j2n
:
Classrooms.find({studentIds: "lof8gzanasd9a7j2n"});
More information on MongoDBs read operations.
Separate collections for students and classrooms seems more straightforward.
I think just keeping a 'classroom' or 'classroomId' field in each student document will allow you to join the two collections when necessary.
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