Data Modeling for MongoDB

Data Modeling for MongoDB
Photo by Zdeněk Macháček / Unsplash

This is a follow on article to our previous article on running your own MongoDB instance on docker. Once you have a docker instance up, try using and extending some of these examples to write data into your running Mongo Database.

Data modeling is an important aspect of working with MongoDB because it allows you to design and organize your data in a way that is efficient, flexible, and scalable. A well-designed data model can help you store and retrieve data more efficiently, and it can also make it easier to update and maintain your database over time.

One of the key features of MongoDB is its support for flexible, document-based data models. This means that you can store data in a JSON-like format called BSON (Binary JSON), and you can organize your data into collections of documents. Each document can contain any number of fields, and you can store different types of data within a single document. This flexibility allows you to store data in a way that is most appropriate for your application, and it also makes it easier to update and modify your data as your needs change.

Overall, data modeling is an important aspect of working with MongoDB because it helps you to organize and structure your data in a way that is efficient, flexible, and scalable, and it enables you to take advantage of the powerful features that MongoDB provides for working with large datasets.

What is a Data Model?

A data model is a way of organizing and structuring data in a database. It defines the relationships between different data entities and specifies how the data can be stored, accessed, and modified.

# A data model is a standard representation of data 
person = {
    "name": "John Smith",
    "age": 35,
    "gender": "male",
    "address": "123 Main St.",
    "phone": "123-456-7890"
}

Data models can be used to represent real-world entities and their relationships, such as customers, orders, and products in an e-commerce application. They can also be used to represent more abstract concepts, such as user profiles, social connections, and event logs.

Data models are not hard to understand, especially if you are familiar with object oriented programming. Take for example below, a representation of a Person class:

class Person:
    def __init__(self, name, age, gender, address, phone):
        self.name = name
        self.age = age
        self.gender = gender
        self.address = address
        self.phone = phone
    
    def to_dict(self):
    	"""Returns the representation of this object as a dict"""
        return vars(self)

# Example usage
person = Person("John Smith", 35, "male", "123 Main St.", "123-456-7890")
print(person.name)  # "John Smith"
print(person.age)  # 35

The dict or json representation of this person object would become after executing person.to_dict() would be:

{
    "name": "John Smith",
    "age": 35,
    "gender": "male",
    "address": "123 Main St.",
    "phone": "123-456-7890"
}

Using the object representation of a person would also allow us to associate functions to the object to that would allow for interesting actions. Perhaps this person that has a phone number would be able to take calls and a accept_call function could be created and allow this person to process messages from a call.

Going from Data Models to turning MongoDB into an Object Database

An object database is a database management system (DBMS) that stores data in the form of objects, rather than tables of rows and columns as in a traditional relational database. Object databases are often used in object-oriented programming languages such as Python, Java, and C++, because they allow you to store and retrieve data using objects and object-oriented programming concepts.

To use an object database, you typically need to define a data model that represents the structure of the data that you want to store. This data model defines the types of objects that you will be storing in the database, and it specifies the attributes and relationships between these objects.

For example, if you were building an e-commerce application, you might define a data model that includes objects such as "Customer", "Order", and "Product", and you might specify the relationships between these objects (e.g., a customer can place multiple orders, an order can contain multiple products). You could then use this data model to design and implement your object database, and to store and retrieve data about customers, orders, and products.

Overall, data models and object databases are closely related because a data model is used to define the structure of the data that is stored in an object database, and the object database is used to store and retrieve data based on that structure.

Taking the above example one step further, the class could be further extended with additional functionality as in the example below:

class Person:
    def __init__(self, name, age, gender, address, phone):
        self.name = name
        self.age = age
        self.gender = gender
        self.address = address
        self.phone = phone

    def update_age(self, new_age):
        """Update the person's age"""
        self.age = new_age

    def update_address(self, new_address):
        """Update the person's address"""
        self.address = new_address

    def update_phone(self, new_phone):
        """Update the person's phone number"""
        self.phone = new_phone
    
    def accept_call(self, expected_person):
        """Accepts a call and responds differently if the expected_person is different"""
        if expected_person == self.name:
        	return f"Hi, this is {self.name}"
        else:
        	return "Sorry, I think you've gotten the wrong number"
            
    def to_dict(self):
    	"""Returns the representation of this object as a dict"""
        return vars(self)

Finally, saving the data into MongoDB:

from pymongo import MongoClient

# Connect to the MongoDB server
client = MongoClient("mongodb://localhost:27017/")

# Select the database and collection to use
db = client["mydatabase"]
people_collection = db["people"]

# Define the Person class
class Person:
	... # using the previous definition

# Create a new Person object
person = Person("John Smith", 35, "male", "123 Main St.", "123-456-7890")

# Convert the Person object to a dictionary
person_dict = person.to_dict()

# Insert the dictionary into the "people" collection
people_collection.insert_one(person_dict)

So far, in this article we've covered the use of classes to create a data model and extending these classes with functions to allow richer interactions with data provided from a database. These extensions are what takes a data model towards an object model representation of data. While we have created simple definitions for these classes, they could be improved with taking json representations of data and converting them into objects.

We have also not covered how objects would be queried from the database using a data model class to transparently fetch data from the database and convert them into objects. We'll cover this in a future article.