Previously I wrote about easily
developing Node.js and Couchbase apps using Ottoman
for ODM. That post was just a taste of what Ottoman can do and how you
can compare it to the things Mongoose can do with MongoDB.

This time we're going to go a step further and see some use cases that makes Ottoman shine.

The Node.js SDK for Couchbase has many different ways to work with documents. CRUD operations, N1QL queries, Couchbase Views, these
are all great things to use, but what happens when your data gets really wild. By wild I mean you have documents with referred
relationships and complex structures. You could use Couchbase Views and CRUD operations, but if your relationships are complex, you're
going to have a lot of Node.js code for data manipulations. You could use N1QL queries, but with complex relationships you're going
to be left with huge complicated queries with a lot of joins. What do you do?

Some Modeling Examples

Let's say we're working with the following document models. We're going to assume this application is some kind of project management
applicaiton.

A Project Model

Given that we are creating projects, we'll not only need information about the project itself, but who is a part of the project. Take the
following Ottoman model as a sample:

In the above model, the owner is a different Ottoman model called User, but the users is an
array of that User model.

A User Model

With the project model in place we need to define the user model in Ottoman. It might look something like this:

The above user model is just standard string data. There are no references to other models like we saw in the project model. Now we
have to worry about querying these two models in the best fashion.

Querying Deep With Ottoman

Let's say we wanted to query for projects within our application. This query would typically look something like this:

The results to this query might look something like the following:

What's wrong here? Well, the query only loaded a shallow amount of data. For example, none of the actual user information loaded,
only the references to those user documents.

So how can we deep query for the other documents? Take a look at this revision to our query:

Notice the use of {load: ["users"]} in this case. This means that we want to load all the user models in the array
when we run our query. How about if we wanted to load the owner documents as well? We would do something like
{load: ["users", "owner"]} to load them as well.

Complicating the Ottoman Model

Now let's change our data model a bit. Let's say our project Ottoman model now looks like this:

Instead of an array of Ottoman models we're now working with an array of objects that happen to contain an Ottoman model.

Changing our Deep Ottoman Query

With the change to our data model comes a change to our query. It doesn't make sense to do {load: ["comments"]} because
comments is not an Ottoman model. There is nothing to load. Instead we have to change our query to look like this:

Notice the use of comments[*].user above. We are loading the user model that exists in all object elements of the
array.

Conclusion

You just saw how to load child models all within a single query. While very possible using a N1QL query, it would take a few
JOIN statements to get the job done. It comes down to your preference, but if you enjoy the ODM approach, Ottoman
and the load option is a great choice.

A full working example of this can be seen in the compiance GitHub project as
well as in a webinar series that I did on full stack development.

Posted by Nic Raboy, Developer Advocate, Couchbase

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.

Leave a reply