DEV Community

Cover image for Keep Calm, and Keep Coding with Cosmos and Node.js
John Papa
John Papa

Posted on • Updated on

Keep Calm, and Keep Coding with Cosmos and Node.js

Coding with the Cosmos DB SDK feels good. Yes, I said feels good. Yeah, yeah … it is fast to install, fast to learn and fast to execute. But most of all it feels good.

Think about when you are coding and everything is just flowing for you. It feels great to be in a rhythm and get everything out of your head and into the code and working fluidly! A key ingredient to this is when the APIs we are coding are intuitive and easy to follow. This is where the Cosmos DB SDK shines brightest. Let's see why.

I Want to Have Fun with the Code Now

Cosmos DB SDK is awesome, feels great, and if you want to feel great too without reading this and try this all yourself - here are the links to get you started. I may cry if you skip reading this, but I'll get over it.

Calm, Cool, Collected Coding

When all is well with the coding universe, coding can be therapeutic for many of us. Other times it can be like a dozen screaming children running through our house with paint guns at a birthday party! (hey, don't judge me)
When we write code we know what we want it to do. For example, recently I wanted a list of heroes from my database - just give them to me without making me work so hard! The line of code that gives them to me with Cosmos DB SDK is simply this:

container.items.readAll().toArray()

There is a container for my heroes, and it has items in it (my heroes). So read them and return them as an array, please. Now that wasn't so hard!

Cosmos DB with Express Routes

OK, so how does this work in context with a Node and Express route for an HTTP request? Let's think this through.

We'll first need to set up the database. We'll do that in another module, so we can stub that out quickly and import it.

Then we get the heroes. OK, we already have that line of code from above. This code is asynchronous, so we'll consider using promises or async/await. It's your call, so choose wisely. Using async/await is what brings me joy, so that's what we'll do here. Here is how it will look as I pull the result out and rename it heroes.

const { result: heroes } = await  container
      .items
      .readAll()
      .toArray();

Finally, if it works we need to stuff the heroes in the response with a status code. If it fails, we return a failure status code and message.

Here is the code I wrote for this. Feel free to borrow it (just return it when you're done, please, so others can borrow it too).

//hero.service.js
const { heroes: container } = require('./config').containers;
async function getHeroes(req, res) {
  try {
    const { result: heroes } = await  container
      .items
      .readAll()
      .toArray();
    res.status(200).json(heroes);
  } catch (error) {
    res.status(500).send(error);
  }
}

That was easy. Like crazy easy! We just wrote database access code and connected it to an express route in a few lines.

OK, there was that one line we stubbed in for the configuration. We'll need to write that, but the good news here is that the configuration only needs to be done once. The fixed cost is a one-time thing that as many functions as you need can re-use. In other words, we can write functions to get, put, post, delete heroes, villains, and whatever we want and only need that single line up top to configure it!

Isolating the Configuration

Here is a module you can use to help get started. I like to isolate the functionality that sets up my coding environment to connect to the database in one Node module. Here we have one that we could call config.js or giraffe.js. I think the former makes more sense, but you do you.

The comments explain what is happening in here, but let's review anyway. First, we reference the Cosmos module from the @azure/cosmos npm package. Then we set up the keys, URL, and database name. This consolidates all of our configurations in one place. Finally, we instantiate the Cosmos client object and expose the container objects. These container objects are what we'll import in other modules, so we can just ask for the container and it just works. Yes, it's that simple.

// config.js
// Get the npm module for Azure's Cosmos
const cosmos = require('@azure/cosmos');
// Identify your database keys and name
const endpoint = process.env.CORE_API_URL;
const masterKey = process.env.CORE_API_KEY;
const dbDefName = 'vikings-db';
// Instantiate the Cosmos client object,
// which is the focal point of interacting with Cosmos
const { CosmosClient } = cosmos;
const client = new CosmosClient({ endpoint, auth: { masterKey } });
// Make it easy to acces the containers
const containers = {
  heroes: client.database(dbDefName).container('heroes'),
  villains: client.database(ddDefName).container('villains')
};
module.exports = { containers };

Try It

You can try this out yourself in your own app, or by cloning my repository here, or by running through a quick start in the documentation.

Here are some links to get you started

This article is cross-posted to my blog

Top comments (2)

Collapse
 
eekayonline profile image
Edwin Klesman • Edited

Thanks for this meditation session, John 🙌🏻.

I've been following your content for many years, and I'm still a fan of your enthusiasm and clean way of explaining things regarding coding.

Collapse
 
john_papa profile image
John Papa

Thanks!