Do What I Mean
February 23rd, 2020
I have done many attempts to wrap my head around MongoDB. As I come from the traditional world of RDBMSs, this does not come naturally to me. But the more I work with Javascript, the more natural the step to Mongo becomes.
So far, my attempts to use Mongo failed, due to my inability to overcome the learning curve. In this post I will discuss one of my the biggest hurdles: embedded documents and many-to-many-relationships.
In the relational world I hardly ever work in the database directly. I almost always use an ORM like SQLAlchemy, Sequelize, or Eloquent. In the past I worked on projects with Meteor which uses Mongo as a backend and uses schemas to help manage your data. Mongoose provides similar functionality, which I like.
Documents in MongoDB are hierarchical by nature. They easily map to JSON and Javascript objects, which makes the match with Javascript so elegant. This means that 1:n relations are modeled by having nested documents.
For example, in my current project organisations have teams, which in turn have members. The organisations data would look like:
[
{
name: "Universal Exports",
teams: [
{
name: "development",
members: [...]
},
{
name: "marketing",
members: [...]
}
]
},
{
name: "ACME",
teams: [
{
name: "design",
members: [...]
},
{
name: "production",
members: [...]
}
]
}
]
Team members are the system's users. Each team has multiple members and every user can be member of multiple teams. This results in a many-to-many-relationship, which can no longer be modeled hierarchically. Instead of containing the user data itself, the members refer to the ids of the users and the users are in their own collection.
Similarly, I could have chosen to make teams a separate collection and have the teams
field of the organisation refer to the team ids. But in that case, a embedded document is more natural as each team belongs to exactly one organisation. Making organisations and teams separate collections would have been the relational way, and then I should have stayed with Sequelize and Postgres.
I run into the limitations of my Mongo knowledge as I attempt to find the teams a user belongs to. I tried some queries in the Mongo client:
db.organisations.find({teams: {members: ObjectId("5e5146d2b941b21ccea02c48")}})
// no response
db.organisations.find({"teams.members": ObjectId("5e5146d2b941b21ccea02c48")})
// gives the correct organisation, but includes all teams
So far, I haven't been able to figure out how to get the relavant teams only. So, I end up writing Javascript code instead of Mongo queries. Hopefully, I will be able to follow-up on this post soon with a solution.