Welcome back! This is the second part to a three-part series discussing data modeling in NodeJS with Orchestrate. In our first part we built a generic Model object which we will continue to build upon here. The end result can be found on git.

Now that we have a functioning Model object we can use to represent our collections we need the ability to create relationships between our Models and define schemas. Finally we’ll discuss common data modeling patterns in JSON with examples using our Model object.

Schema and Validation

Document Stores are highly flexible. The database itself does not impose any type of constraint, documents are stored as is. This flexibility is great for getting something off the ground fast, but as the properties of your document evolve, you may create fragmented documents and find yourself writing exceptions in your models to fill in the gaps.

By creating a simple schema you document the structure of your objects and provide a convenient point for data validation. A few minutes up front will save you hours of frustration down the line.

Instead of building a JSON schema validator from scratch lets let our Model take an optional validation method. This way the developer can use which ever method they feel is best. This validation method must accept an object that is serializable to a JSON document, and return true if passed or errors if it doesn’t. If set, the method is called anytime a document is saved or created.


var Orchestrate = require(‘orchestrate-bluebird’)
var jjv = require(‘jjv’)

var movieDb = Orchestrate.connect(‘’)
jjv.addSchema(‘movie’, {
    type: 'object',
    properties: {
        title: {
            type: 'string',
            minLength: 2,
            maxLength: 15
        description: {
            type: 'string',
            minLength: 10,
            maxLength: 300
    required: [‘title’, ‘description’]

var options = {
    validate: function (obj) {
        var errors = jjv.validate(obj)
        if (!errors) {
            return true
        } else {
            return errors
var MovieModel = Orchestrate.model(‘movie’, movieDb, options)

If a validation method is not supplied the default validate() will always return true. Above, I make an example using JJV which is a JSON-schema validator. JSON-schema is a standard for describing a JSON document, using JSON. It’s easy to read, has lots of support and fits in well with the javascript ecosystem.


The last thing we need before data modeling is the ability to create relationships between different documents across our collections. An example would be to create an “actors” relationship from a movie object to corresponding actor objects:


Orchestrates Graph API lets us create one-way, named relationships between any document in your Orchestrate Application. Lets introduce two generic methods, relate() and getRelation(). relate() accepts another Model object and a relationship name, or a key, collection and relationship name to create relationships. getRelation() takes a relationship name and a Model class then returns a list of matching Models.

Building on the MovieModel from the first figure:

MovieModel.prototype.addActor = function (actor) {
    return this.relate(actor, ‘actors’)

MovieModel.prototype.actors = function () {
    return this.getRelation(‘actors’, ActorModel)

Getting all actors:

.then(function (movie) {
    return movie.actors()
.then(function (actors) {
    for (var i = 0 ; i < actors.length; i++) {

Relating an actor to a movie:

ActorModel.findOne(‘Kevin Bacon’)
.then(function (actor) {
    return MovieModel.findOne(‘Tremors’)
    .then(function (movie) {
        return movie.addActor(actor)

Data Modeling with JSON

Now that we can define a schema and create relationships, lets consider data modeling for NoSQL. While Orchestrate uses JSON, these methods could easily be applied to other types of stored documents (XML, HTML, etc).

When designing data models, consider the structure of the document, how it relates to other data, and the effects on performance in your application. Requests to Orchestrate are atomic with no option for batch requests. How and when your application interacts with data is an important consideration. Document relationships can happen as embedded documents or references.

Embedded Document

Embedded objects are a single document with all pieces of related data stored together. This denormalized structure allows all the data to be acquired in a single request.

JSON movie document:

    “title”: “Tremors”,
    “director”: {
        “name”: “Ron Underwood”,
        “birthday”: “November 6, 1953”

This method optimizes read operations and atomic updates for related data, but can cause data duplication, unexpected document growth and complicate writes. Because the director of a film is not likely to change, our example of the director sub-document would work. However, it would introduce significantly more write operations if Mr. Underwoods name had to be changed.


A document that describes it’s relationships with references typically contains a key or id that tells the application where else to look for related data. Orchestrate accomplishes this with it’s Graph API so there is no need to include such references in your document structure.

You can create named relationships between any document in its Orchestrate application. The burden of managing these relationships falls solely on your application and will increase the number of read operations per relationship. This method reduces data duplication, and makes write operations much simpler.

When designing your data models take the following into consideration:

  • How often is the document likely to change?
  • Do increased database operations hurt the user experience?
  • Will I be using server side caching?

The work required to switch from embedded to reference is significant where the opposite is true when switching from reference to embedded.

Design your data model, enforce it with a schema validator, and build sensible data relationships for your application. These three up front will save you later heartache.

In part three, we’ll round up some final features for our Model class including audit logging and using Orchestrate Refs and Events.