NoSql One-to-Many Relation Examples; Bound And Unbound Cases

What Are The Options To Properly Model 1-to-Many Scenarios And Which One Is Right?

In NoSql data modeling post I’ve explained NoSql data modeling and that there are three ways to model one to many relationships. In this post I’ll list real-world examples of one to many relationship — both bound and unbound — in which application of different ways of modeling are possible (or not).

One To Many Bound

Let’s take an example of Restaurant has many Workers. If we analyse this relation it’s obvious that it’s bound by an upper limit. Workers working in a restaurant will always be limited in numbers e.g. 100, 200, 1000, 2000, at worst 3000? No matter what, they are never going to be out of control even increased by thousands, and we are absolutely sure of it. So, we can say the relationship is bound.

Let’s take another example: Airplane has many Parts. We’re well aware how many parts an airplane (say passenger jet) has: millions. Since plane parts are not increasing, the relation is still bound. However, out of two options mentioned below only option 2 is feasible because otherwise plane document will get too large to be manageable (or even allowed by dbs).

The modelling options are two: array of references on one side; or reference of belonging document on another. Here are the examples:

Option 1

Restaurant

{
    id: "restaurant1",
    .
    .
    .
    .
    workers: ["worker1", "worker2", "worker3"]
}

Workers

{
    id: "worker1",
    .
    .
    .
}
{
    id: "worker2",
    .
    .
    .
}
{
    id: "worker3",
    .
    .
    .
}


Plane

{
    id: "plane1",
    .
    .
    .
    .
    parts: ["part1", "part2", "part3" ...] //can't hold millions of references here!
}

Parts

{
    id: "part1",
    .
    .
    .
}
{
    id: "part2",
    .
    .
    .
}
{
    id: "part3",
    .
    .
    .
}

Option 2

Restaurant

{
    id: "restaurant1",
    .
    .
    .
    .
}

Workers

{
    id: "worker1",
    .
    .
    .
    restaurant: "restaurant1"
}
{
    id: "worker2",
    .
    .
    .
    restaurant: "restaurant1"
}
{
    id: "worker3",
    .
    .
    .
    restaurant: "restaurant1"
}


Plane

{
    id: "plane1",
    .
    .
    .
    .
}

Parts

{
    id: "part1",
    .
    .
    .
    plane: "plane1"
}
{
    id: "part2",
    .
    .
    .
    plane: "plane1"
}
{
    id: "part3",
    .
    .
    .
    plane: "plane1"
}

One To Many Unbound

Next comes unbound relation. An example would be a Post has many Visitors. That is to say, we record each and every view of our post and also some basic information such as ipAddress, browser, deviceType (desktop, tablet, mobile) etc.

Even if we expect a few thousand views a post at maximum, we’re not sure that will always be the case. What if a post gets viral and attract million plus views? And when the post is to remain there years onwards, there’s good chance one million will become two million in no time. Therefore, we have a case of unbound one to many relationship.

From two options mentioned above, option 1 will not work for the same reason it didn’t work for plane/parts. Only, option 2 works:

Post

{
    id: "post1",
    .
    .
    .
    .
}

Visitor

{
    id: "visitor1",
    .
    .
    .
    post: "post1"
}
{
    id: "visitor2",
    .
    .
    .
    post: "post1"
}
{
    id: "visitor3",
    .
    .
    .
    post: "post1"
}

Conclusion

To sum up one to many examples above:

  • If bound and small, reference can be placed on either side

  • If bound but too large to keep references array, reference should be placed in belonging documents

  • If unbound, reference should always be kept in belonging documents