I was recently at two different Meetup groups in Southern California presenting on what I’m calling, the OCEAN stack, which is composed of Ottoman.js, Couchbase Server, Express Framework, Angular, and Node.js.

We had a great turnout of developers hungry to learn about a JavaScript with NoSQL stack.

OC Angular Meetup

As per my promise to the groups, I have done a tutorial write-up of the content that I shared so that way everyone can benefit. We’re going to see how to develop a functional web application using various JavaScript technologies and NoSQL.

Before jumping into the code, the assumption is that you’ve got Couchbase Server installed and configured as well as Node.js. The focus here will be development, not environment configurations.

We’re going to build an API using Ottoman.js and then with N1QL instead of Ottoman.js. Both APIs will be consumed by a front-end developed in Angular.

Developing an API with Ottoman.js, Express Framework, and Couchbase NoSQL

The first step in any Node.js project is to configure a project and download all the dependencies. Creating a fresh project and downloading the dependencies can be handled with the following commands:

The first command will create the project’s package.json and the second command will get our dependencies which include the body-parser for accepting JSON bodies in the request and the cors package for cross-origin related issues that might come up when using Angular on a different domain or port.

To bootstrap our application, we’re going to create a file called app.js that contains the following JavaScript code:

Essentially we’ve just imported our downloaded dependencies, defined our API endpoints, established a connect to Couchbase Server, and started serving the application.

The API endpoints will be for basic CRUD operations against our database. Because we’re using Ottoman.js which is an object document modeler (ODM), we need to define our model. Above the endpoint definitions, add the following:

This model can be infinitely complex, but ours will just represent a simple user profile. This is the model we’ll manipulate in our code as well as the database.

Because our database is currently empty, it makes sense to work on our endpoint for creating data. Edit the following chunk of JavaScript within your project:

The above endpoint is probably the most complex part of our project. We are saying that we are requiring a POST body. It doesn’t matter what it is, as long as it exists.

We hit two birds with one stone in this endpoint. We are accomplishing a create as well as an update. First we do a lookup by the passed id. It doesn’t matter if an id was passed or not. If there was an error for reasons of maybe an id not existing, a new ODM model will be created based on our definition, otherwise it will be merged with what we got from our lookup based on id.

Once we have our model complete, we can save and return the results to the user.

The next logical step is to complete the endpoint for finding a particular person by their id value. Add the following JavaScript to your project:

Using a passed id value we can get someone from the database and return it back to the client that had issued the request.

There might be times where we want to get all records that match the model. There may even be times where we wish to query based on properties other than the id value. In this case we can use a find command:

By providing an empty object in our command, we are requesting all documents that match the model. This could have easily been extended to particular matching properties. We also want to make sure that our index is updated before we complete the query. By default, Couchbase is performance focused which means if your index hasn’t updated yet, your results might be missing some data. Depending on the circumstance, you can change the scan consistency like we have in the above.

Finally, we can build our endpoint for removing documents from the database:

We first obtain a document by the passed id, and if it exists, we can issue a remove on it to delete it.

If you run this application and use a tool like Postman, you can test your basic, but fully functional API.

Developing an API with Express Framework, N1QL, and Couchbase NoSQL

Let’s say that using an ODM like Ottoman.js is not your jam and you’d prefer to fabricate your own queries. Removing Ottoman.js gives us the CEAN stack and it is made possible with N1QL.

While our project structure will be quite similar, we’re going to create a new project for our own sanity.

We have similar dependencies as seen in the previous project, but this time around we are obtaining a package for generating UUID values. Ottoman.js created id values for us, but with N1QL, it is up to the developer. One of many ways to create an id is via a UUID.

Within a new app.js file, you might have the following boilerplate code:

That should look pretty familiar, but this time we swapped out Ottoman.js with N1QL preparation.

Just like with the previous example, we’re going to worry about saving data before we try to read from the database. Check out the following endpoint code:

If we receive an id with our request, we’re going to use it and assume we are doing an update, otherwise we’re going to generate a new id and do a create. Both operations can be accomplished with a single UPSERT query. To prevent SQL injection attacks, we’re going to use a parameterized query to parameterize our user defined data.

If we know the id and we wish to find a particular document, we can use a SELECT query for the job:

In both queries we are returning either the error or the results back to the client that issued the request.

If we wish to query for all our documents, we can drop the WHERE condition and define our scan consistency like so:

Being that N1QL is just another flavor of SQL, our query possibilities are quite large. This API example doesn’t even cover a fraction of what is possible.

Finally if we wanted to remove a document by its id value, we could do something like the following:

None of these N1QL based endpoints were difficult. There is no wrong choice when it comes to Ottoman.js or N1QL, it really just comes down to preference.

Building a Client Frontend with Angular and TypeScript

With the backend API out of the way, we can focus on a very simple, but functional client frontend. This frontend will work with both our OCEAN stack and our CEAN stack example. It is always nice to have something modular.

Assuming you have the Angular CLI installed and configured, we need to have a fresh project:

The above command will create a new project with all our required Angular dependencies.

At this point you can either use the CLI to generate each of our pages, or do them manually. Both will put you in the same place.

Create the following files and directories in your project however you want:

Starting with what will be our AlterComponent, open the project’s src/app/alter/alter.component.ts file and include the following TypeScript code:

There is a lot happening in the above code, so let’s break it down.

Inside the constructor method we have the following:

We are initializing our public variables, one that represents our form data and the other that represents a possible id for an existing document. In addition to this we are also injecting several Angular services for use in the component.

Again, we are going to hit two birds with one stone. This component will represent a screen for creating and updating documents.

Within the ngOnInit method we take a potential document id and do a lookup for the data that resides at it:

If no id is present, nothing will happen and our input variable won’t be populated with anything beyond empty strings. The lookup will be an HTTP request against the API endpoint that we had previously created either with Ottoman.js or N1QL.

The last thing to do for this component is save:

If an id is present, we’ll pass it with our POST request. The POST request will have the serialized form data. Provided the request was successful, we can navigate to the previous screen.

The HTML that goes with this TypeScript logic can be found in the project’s src/app/alter/alter.component.html file and it looks like the following:

I’m not much of an artist, so this HTML will be very basic and not styled at all. Notice that each form element is bound to our public input object.

The second and final component to the project is for listing any saved documents. Open the project’s src/app/list/list.component.ts file and include the following TypeScript code:

Again, we’ll break it down.

Within the constructor method we initialize our public variables:

In this case, the public variable is our list of documents that will display on the screen. The next step is to query for anyone who might exist and populate the now empty array:

By now you might have noticed that the frontend is mostly just a bunch of HTTP requests to our API. The backend does much of the heavy lifting.

We need to query for documents both when the application loads and when we navigate backwards in the Angular navigation stack. This can be seen in the ngOnInit method:

We need to subscribe to the location listener so we can determine when we’ve navigated backwards. We do this because the constructor and ngOnInit methods trigger only when navigated to, not navigated back to.

This takes us to the removal of documents:

In the HTML we’ll have a button next to every list item. This button will allow us to remove documents by calling the delete method and passing in the particular document id. If successful, the item will be removed from the database and locally in the array.

The HTML behind this logic can be found in the project’s src/app/list/list.component.html and it looks something like this:

The routerLink attribute will navigate us to the page for creating or updating data. Then we loop through our array, presenting each document on the screen. If the item is clicked, we navigate to the update page and pass the id of the document that was clicked. This allows us to pre-populate the form. Otherwise, if we want to delete a document, we click the other button.

Even though the core content is done with the Angular side of things, we need to bring it together via the Angular Router.

Open the project’s src/app/app.module.ts file and include the following:

Notice we’ve just imported our components and defined a route for each of them. Nothing too fancy going on there.

Depending on your version of the Angular CLI, you might need to alter the project’s src/app/app.component.html file to contain the following:

This allows navigation to work in the project.

Conclusion

You just saw the OCEAN stack and CEAN stack material that I presented on at the Angular Orange County group and the Couchbase Los Angeles group.

If you’re a MongoDB developer and looking into Couchbase for the first time, you might have a look at a cookbook that I wrote that dives deeper into Ottoman.js and N1QL while explaining how to move from MongoDB.

For more information on Couchbase and Node.js, check out the Couchbase Developer Portal.

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