Defining one to one and one to many relationships in node js for a mongo DB using mongoose.

karegyeya calvin
5 min readApr 18, 2021
Photo by Jan Antonin Kolar on Unsplash

MongoDB is one of the most popular NoSQL databases and its very popular for creating flexible and dynamic database schemas. It is a document database meaning that it stores data in JSON- like documents. It supports arrays and nested objects as values. The makers of mongoDB believe this is the most natural way to think about data, and is much more expressive and powerful than the traditional row/column model.

Since mongoDB is schemaless and does not require the same rigid schemas used by relational databases, it leaves questions on what rules to follow when setting up database architecture for NoSQL databases. Even though schemaless will give much flexibility to your application, it doesn't mean that there is no need to set up powerful and secure database architecture. And besides the better the database architecture the more efficient the application it supports.

In this tutorial, I will walk you through how to set up one to one and one to many relationships for mongoDB more efficiently.

NOTE: There is no right or wrong way to set up a mongo database since its schemaless. However given my experience working with mongoDB application, I believe the tricks in this tutorial will teach you how to efficiently implement mongoDB model relationships.

Prerequisites.
* ExpressJS
* mongoDB
* NodeJS and NPM
* mongoose ORM

Lets start by using the following scenario that we need to create an application for.
Consider a university system where involving the following objects student, report, staff, program and school.
Database constraints
1. A student can have one report. A report belongs to one student.[one to one relationship]
2. A student belongs to one school. A school can have one to many students.[one to many relationship]
3. A student can only take one program at a time. A program can be done by one to many students.[one to many relationship]

One to one Relationship

We will begin by creating these individual schemas using mongoose schema.

I will consider 3 options for implementing this kind of relationship.
Option 1
Student schema.

Student schema

You notice the report property on the student model has type ObjectID, and a ref of report. If you have used mongoose, you should know that this is how we can declare foreign keys on a collection(table for sql db). This implies that the student schema is linked to the report schema through the reportID which should be got from the report object.

Report schema

Report schema

You will notice that the report model does not have a ref to the the student model. You should be wondering why I choose to have the foreign key in the student schema and not the report schema after all its a one to one relation. The answer is simple but before I give you the answer, I will explain why I don’t prefer the other two options of implementing a one to one relationship.

Option 2

This option would include a ref property in the student collection and the report collection. This approach seems to look ok because you can find the corresponding record from the other collection simply by populating that field on either models. The downside to this approach would be;
* There would cyclic foreign keys which would bring about confusion how how to create and fetch data from the database. Whenever a student object is created, it should have a report attached to it and whenever a report object is created, it should have a student attached to it.

Option 3

This option would include a ref property only in the report collection. This option would also work but the only challenge is that the report object is inanimate(implies it not alive). The only objects that are not inanimate in the system are the user objects. This is why Option 1 is the best approach and I will explain why.

Since your modeling your database to be efficient enough to be consumed by your application. You have to keep the flow of the application in your mind. Logically we expect the students to sigin into the system first so that they can submit and access their reports. This is a mechanism that is used to prevent unauthorized access to data with in the system. This implies that we already have the student object by the time we need to access the report object through sigin therefore there is no need to query the report collection in order to find the student report because it is already attached to the student through the foreign key. There are very few or no instances in your application where you will find yourself getting the report object first and then querying to get the corresponding student object. This is why I choose to add the foreign key in the student model.

In my approach, the decision is made based on which collection object owns the objects in the other collection. In most applications you will find that the User objects are owning the inanimate objects implying that user objects will always take up the foreign key reference.

Other examples include
In a logistics system. A transporter can have only one vehicle and a vehicle belongs to only one transporter. Here the ref should be included in the transported schema.

Conclusion

One to one relationships can occur between 2 inanimate objects. My approach chooses to have the foreign key reference in the collection whose objects own the other objects. But mostly one to one relationships will occur between a user object and an inanimate object of the system. I want to keep this tutorial simple so click here to read about one to many relationships in mongoDB using mongoose.

--

--