Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Object Relations in a NoSQL Database

DZone's Guide to

Object Relations in a NoSQL Database

Objects and relations are a crucial part of any application. By letting the database do the job of maintaining this logic, you will save yourself a ton of work.

· Database Zone ·
Free Resource

MariaDB TX, proven in production and driven by the community, is a complete database solution for any and every enterprise — a modern database for modern applications.

Compared to a traditional relational database (SQL), a document-oriented (NoSQL) database has poor or non-existent support for relations between objects (data schema). A NoSQL datastore persists and retrieves documents (often in JSON format) and any relationship between your documents is something you must implement yourself.

Without any direct support for relations, you’re stuck with the logic and maintenance of objects/relations in your application layer.

This blog post shows how you can leave the job of maintaining object/relations to a database, effectively giving you time to pick from your backlog instead of adding.

Example Application

As a context for this blog post, we'll create a simplified data schema for an issue-tracking application.

An issue-tracking application typically lets customers reports issues, and someone in the organization is selected as a responsible contact for the follow-up and for ultimately resolving the reported issue.

The illustration below shows the three main objects of our application.

illustration

This simplified model has two explicit relations from the issues object:

  1. An issue is linked to one customer.
  2. An issue has one responsible.

The model also has two implicit relations:

  1. A customer can have many issues.
  2. A responsible can have many issues.

Our simple data model reveals that there are four object/relations that must be maintained in our issue tracking application.

Creating a Schema With Relations

With the example above in mind, let's go ahead and show how we can create data consistency and flexibility by using relations in our JSON documents.

Just as in a traditional relational database, we'll start by creating one collection (table) for each of our main objects.

In restdb.io development mode, we add the three collections by clicking on the Add Collection button. The screenshot below shows the result:

screen shot schema

For this example, we'll also add some random data using the random data generator.

After running the random data generator on each collection, our database now has these populated data collections.

The customers collection:

[
  {
    "_id": "58feea7ebcb53e0d000009ca",
    "customer-name": "Von Group"
  },
  {
    "_id": "58feea7ebcb53e0d000009cb",
    "customer-name": "Tromp Inc"
  }
  ...
]

And the issues collection:

[
  {
    "_id": "58feeab2bcb53e0d000009cc",
    "title": "Printer ink",
    "description": "It's empty in 2. floor. Please fix asap!"
  },
  {
    "_id": "58feeae1bcb53e0d000009d0",
    "title": "Sloow network",
    "description": "Everything just hangs before log in."
  }
  ...
]

And the responsible collection:

[
  {
    "_id": "58feea60bcb53e0d000009b8",
    "name": "Hane.Dante"
  },
  {
    "_id": "58feea60bcb53e0d000009c1",
    "name": "Modesta_Grady"
  },
  ...
]

Creating a Relation With the REST API

Adding relations to objects are done with a REST API call.

In this example, we'll use the PUT verb to add a relation to a customer and a responsible on a specific issue. We do this by providing the ObjectIDs for the particular customer and responsible documents:

PUT /rest/issues/58feeab2bcb53e0d000009cc

{ 
    "title": "Printer ink",
    "description": "It's empty in 2. floor. Please fix asap!",
    "customer": ["58feea7ebcb53e0d000009ca"], 
    "responsible": ["58feea60bcb53e0d000009c1"]
}

After validation the document, the database will produce a result for the modified issue document with an embedded copy of the customer and the responsible documents:

{
    "_id": "58feeab2bcb53e0d000009cc",
    "title": "Printer ink",
    "description": "It's empty in 2. floor. Please fix asap!",
    "customer": [
      {
        "_id": "58feea7ebcb53e0d000009ca",
        "customer-name": "Von Group",
        "_created": "2017-04-25T06:19:42.875Z"
      }
    ],
    "responsible": [
      {
        "_id": "58feea60bcb53e0d000009c1",
        "name": "Modesta_Grady"
        "_created": "2017-04-25T06:19:12.182Z"
      }
    ]
  }

Note that a relation is always represented as an array of objects.

What Happened Here?

For each reference to an object (i.e. relation), the database will keep track of any changes in the original document.

On a change in the original document, i.e. the customer name, the database will also update all copies of that instance — hence keeping data consistency and enabling fast atomic queries.

copy

Who's Looking at Me?

The examples above has shown how issues can have embedded copies (relations) of both customers and responsibles. This is great for speed and consistency.

But how do we find the (implicit) issues that belongs to a specific customer or which issues a specific responsible person has?

Well, since the database keeps track of all relations, it can also tell us where a specific document is used in a relation.

The example queries below shows how you can track the implicit references to a document by using a special query parameter: referencedby=true.

By using this parameter in a query, the database will return the full graph for all other documents that has a relation to the document in the query, i.e. find all issues for the customer 58feea7ebcb53e0d000009ca:

/rest/customers/58feea7ebcb53e0d000009ca?referencedby=true

Result is a full graph of the issues for this customer.

{
  "_id": "58feea7ebcb53e0d000009ca",
  "customer-name": "Von Group"
  "_referencedby": [
    {
      "collection": "issues",
      "references": [
        {
          "_id": "58feeab2bcb53e0d000009cc",
          "title": "Printer ink",
          "description": "It's empty in 2. floor. Please fix asap!",
          "customer": [
            {
              "_id": "58feea7ebcb53e0d000009ca",
              "customer-name": "Von Group",
              "_created": "2017-04-25T06:19:42.875Z"
            }
          ],
          "responsible": [
            {
              "_id": "58feea60bcb53e0d000009c1",
              "name": "Modesta_Grady",
              "email": "Arno.King@gmail.com",
              "_created": "2017-04-25T06:19:12.182Z"
            }
          ],
          "_created": "2017-04-25T06:20:34.441Z",
          "_changed": "2017-04-25T06:20:34.441Z",
          "_version": 0
        },
        {
          "_id": "58feeae1bcb53e0d000009d0",
          "title": "Sloow network",
          "description": "Everything just hangs before log in.",
          "customer": [
            {
              "_id": "58feea7ebcb53e0d000009ca",
              "customer-name": "Von Group",
              "_created": "2017-04-25T06:19:42.875Z"
            }
          ],
          "responsible": [
            {
              "_id": "58feea60bcb53e0d000009c1",
              "name": "Modesta_Grady",
              "email": "Arno.King@gmail.com",
              "_created": "2017-04-25T06:19:12.182Z"
            }
          ],
          "_created": "2017-04-25T06:21:21.390Z",
          "_changed": "2017-04-25T06:21:21.390Z",
          "_version": 0
        }
      ]
    }
  ]
}

Find all issues for a specific responsible. The same format is returned here.

/rest/responsible/58feea60bcb53e0d000009c1?referencedby=true
{
  "_id": "58feea60bcb53e0d000009c1",
  "name": "Modesta_Grady"
  "_referencedby": [
    {
      "collection": "issues",
      "references": [
        ...
      ]
    }
  ]
}

Summary

Objects and relations are a crucial part of any application. By letting the database do the job of maintaining this logic, you will save yourself a ton of work.

At the same time, you will keep the speed and flexibility of a document database, combined with the consistency and integrity of a relational database.

Further reading:

MariaDB AX is an open source database for modern analytics: distributed, columnar and easy to use.

Topics:
database ,nosql ,object relations ,schemas

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}