Explore cosmos with Serverless
Tags: serverless, javascript, tutorial, showdev
Published: 2019-06-29 11:38:47

---
title: Explore cosmos with Serverless
published: true
description: Serverless, JavaScript and CosmosDB
tags: serverless, javascript, tutorial, showdev
cover_image: https://thepracticaldev.s3.amazonaws.com/i/3lz77fmx35f6qoaysxti.gif
---

Follow me on [Twitter](https://twitter.com/chris_noring), happy to take your suggestions on topics or improvements /Chris

> You thought this was about space didn't you? Yea my bad :). But now that I have your attention let's talk about Serverless and how we can use that with Azure Cosmos DB. It's so easy it's out of this world ;)

![](et.gif)

What we are going to do is show:

- **Serverless** and how to create a function in the Cloud
- **Create** a Azure Cosmos DB database
- **Show** how can read and write data to your Azure Cosmos DB

## Serverless - look Ma no servers

Serverless is *the new black*, the thing that everybody talks about and for good reason. Gone are the days when you had that server room with no oxygen and full of cables and lord knows what else.

Now you can just focus on the code and rest assured that your code lives in someone else server room ;), that is *the Cloud*. The point is, it's not a thing you need to care about anymore. 

Serverless is, of course, a bit more than just *no servers*, it's fully managed, there is not even a web server to configure. I've covered the *whys* and what offerings in this [article](https://dev.to/azure/serverless-from-the-beginning-using-azure-functions-azure-portal-part-i-28o1), so if you are interested, go and have a read.

We will focus on a specific offering namely Azure Functions.
The reason it's chosen for this specific article is:

- **Easy to get started with** , comes with great extensions for all major IDEs including VS Code that lets you scaffold functions, debug and more.
- **Creates a connection** to your Azure Cosmos DB database so you can just focus on changing the data and not having to bother with instantiating connections

## Resources

- [Free account Azure account](https://azure.microsoft.com/en-gb/free/?wt.mc_id=devto-blog-chnoring) You will need to sign up on Azure to use Azure CLI and deploying Azure Functions
- [How to install azure cli](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest&wt.mc_id=devto-blog-chnoring)
For some of the activities, we do we will use Azure CLI in the terminal. This is a great way to manage your resources.
- [Create an Azure function in VS Code](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-function-vs-code?wt.mc_id=devto-blog-chnoring),
This will show you how to build your first Azure Function in VS Code
- Working with Azure Cosmos DB + Azure function
- [Working with Azure Cosmos DB and Node.js](https://docs.microsoft.com/en-us/azure/cosmos-db/create-sql-api-nodejs?wt.mc_id=devto-blog-chnoring) This article takes you through building a Node.js app, create an Azure Cosmos DB app and connect the two.
[Create an Azure Cosmos DB using Azure CLI](https://docs.microsoft.com/en-us/azure/cosmos-db/manage-with-cli?wt.mc_id=devto-blog-chnoring)
This shows how you can set up your Cosmos DB database using the Azure CLI
[Create an Azure Cosmos DB using Azure CLI + additional resources](https://docs.microsoft.com/en-us/azure/cosmos-db/scripts/create-database-account-collections-cli?toc=%2fcli%2fazure%2ftoc.json?wt.mc_id=devto-blog-chnoring)
This shows all the different resources you might need to create before and during setting up Azure Cosmos DB, a bit longer version than the above link
- [Series I wrote on getting started with Serverless](https://dev.to/azure/serverless-series-16o8)
- [Serverless CRUD with Azure Cosmos DB client](https://github.com/simonaco/pbp-serverless)
This is a repository by my colleague Simona Cotin that shows how you can do a full CRUD using the MongoDB client
- [Reference page for Serverless + Azure Cosmos DB at GitHub](https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/azure-functions/functions-bindings-cosmosdb-v2.md)
This is the most complete page there is on the combination Serverless + JavaScript + Azure Cosmos DB
- [Slack WebHooks](https://slack.com/intl/en-gb/help/articles/115005265063-incoming-webhooks-for-slack)
- [Better looking Slack messages with attachments](https://api.slack.com/docs/message-attachments)

## Steps
Let's look at this from a mile-high view and see what we need to do, to accomplish what we want. We need to:

1. **Scaffold** a Azure Cosmos DB database in Azure
2. **Create** a Serverless app and create an Azure Function for each call. We show how you can read data, create it and update it
3. **Configure** our functions, to connect to our database, so working with the database is made real easy

## Create a Azure Cosmos DB database

Ok. There are two ways to do this. We can either:

- **Create** it through the Azure CLI
- **Use** the portal and create the database

Let's show how to do it in the `Azure-CLI` at first and then switch to the terminal gradually. Let's face it, it's great to feel like a hacker but sometimes you want to see what you are doing. You also want to make sure it's all there and some things are more practical to do in a UI, like data entry.

### Using Azure CLI

To create the database we need to take the following steps:

1. **Resource group**, Create a resource group for our database or use an existing group
2. **Azure Cosmos DB**, Create a Azure Cosmos DB account
3. **Database**, Create the database
4. **Add** collections and data

**Create the resource group**

```
az group create \
    --name mycosmosgroup \
    --location "West Europe"
```

![](https://thepracticaldev.s3.amazonaws.com/i/g2lbhb61ykxj3bw8oqs7.png)

The above says `"provisioningState": "Succeeded"`, which means we succeeded in creating our resource group.

**Create the Azure Cosmos DB Account**
Next step is about creating our own account. The account name should be lowercase. 

```
az cosmosdb create \
    --resource-group mycosmosgroup \
    --name cosmosaccount-chris-sql \
    --kind GlobalDocumentDB \
    --locations "North Europe"=0 "West Europe"=1 \
    --default-consistency-level "Session" \
    --enable-multiple-write-locations true
```

This might take a little while. All databases take a little time to scaffold. 

If you are impatient you can go visit it in the portal and it should look something like this:

![](https://thepracticaldev.s3.amazonaws.com/i/ipo9zujz20hn7uuloahp.png)

Last step is to create the database. 

**Creating the database**

Ok, we have a database account but we don't have a database, yet. Now, to create a database we need to create something called a *container*. Let's head to the portal and find our database account. Now click the tab `Data Explorer`. It should now look something like: 

![](https://thepracticaldev.s3.amazonaws.com/i/lmh3yqezefi6ip1kkdsz.png)

By hitting the indicated button we get a dialog opened that's asking us to create a new container, like so:

![](https://thepracticaldev.s3.amazonaws.com/i/xad0l96g3oivm5p14cwr.png)

Fill in values for the highlighted parts. You will notice that the `Partition key` will prepend the value with a `/` so `id`, becomes `/id`.

I know what you are thinking, what the heck is a partition key? Let's see what the info icon tells us:

![](https://thepracticaldev.s3.amazonaws.com/i/kj781lrr13a32th5eitl.png)

Partitions are a chapter all to itself. If you are really interested in knowing more have a look at this [article](https://blog.maartenballiauw.be/post/2012/10/08/what-partitionkey-and-rowkey-are-for-in-windows-azure-table-storage.html) 
For now, we are happy knowing it's a column we point out in our table.

Ok, so we created our container and we should have something looking like this:

![](https://thepracticaldev.s3.amazonaws.com/i/6ztcoxyxusf0xmwelaxr.png)

Now what? Now we fill it with data and we do that by clicking the `New Item` button. It should present you with an edit view like so:

![](https://thepracticaldev.s3.amazonaws.com/i/r3gbi4y1f1ljyp8folsx.png)

So change the item to say:

```
{
  "id": "1",
  "name": "tomato"
}
```

Now hit `Save` and repeat the procedure and create another item with the value `{ "id": "2", "name": "lettuce" }`.

We want to show this data in a Serverless function right? Right?

Yea I thought so :)

So Serverless is next.

## Serverless - Reading and Writing to/from our database

Ok then, Serverless part it is. We need to support interacting with our Azure Cosmos DB database 

We will build the following:

1. An Azure Function App, this will hold all of our functions
2. Three different Azure Functions, each supporting an HTTP verb
3. *in/out* bindings to Azure Cosmos DB, this is configuration we write that creates a database connection for us

### Create an Azure Function App

To be able to use Azure Functions they need to exist inside of an Azure Function app. We will create it using VS Code so we need to make sure we have the correct extension installed.

So look for `Azure Functions` in the extension area. It should look like this:

![](https://thepracticaldev.s3.amazonaws.com/i/gkl1rs6toru3ilmnti2m.png)

Next step is to scaffold our app.

We do that by opening up the command palette. That is done by either selecting `View > Command Palette` in the menu or you can hit `CMD + SHIFT + P`, if you are on a Mac. 

![](https://thepracticaldev.s3.amazonaws.com/i/adf6m44bse86yewrzz3z.png)

Select the current directory, JavaScript as language and HTTP trigger. The last will ensure that your project contains at least one function. Name the function `ProductsGet` and give it `Anonymous` as authorization level.

### Create remaining functions
For this step, we need to bring up our command palette again. `CMD + SHIFT + P`. Select `Azure Functions: Create Function` and select `HttpTrigger`. Name the function `ProductsCreate`. 

Now repeat this process and create another function called `ProductsUpdate` 

![](https://thepracticaldev.s3.amazonaws.com/i/0w4ytzw2fmft0y23q9sy.png)

We should now configure the allowed HTTP methods for each function. Go into each function directory and open up `function.json`. There you will find `bindings` and specific config looking like this:

```json
"methods": [
  "get",
  "post"
]
```

Ensure you configure it in the following way:

- `ProductsGet`, should only support `get`
- `ProductsCreate`, should only support `post`
- `ProductsUpdate`, should only support `put`

### Configure functions with Azure Cosmos DB

Next up we need to revisit the `function.json` for each function. This time we need to add a binding that lets us talk to our Azure Cosmos DB database. 

Essentially we need to create something called a *binding* that not only holds a connection to our Azure Cosmos DB database but also easily lets us do a CRUD on a specific collection.

The configuration looks pretty much like this:

```
{
  "name": "productDocument",
  "type": "cosmosDB",
  "databaseName": "ToDoList",
  "collectionName": "Items",
  "createIfNotExists": true,
  "connectionStringSetting": "CosmosDB",
  "direction": "in"
}
```

Depending on what we are trying to do we either need a binding of `"direction": "in"` or for it to be binding of type `out`, in which case it would look like this `"direction": "out"`.

If we only want to read data we need this to say `"direction": "in"`. Creating we need it to say `"direction": "out"`. Updating is a different matter, in fact, we need two sets of bindings, one that retrieves our record and one to create/replace our record, more on that later.

So what are we saying here? We are saying that we have a `databaseName` called `TodoList`, change that to whatever you called your database. We also have a `collectionName` called `Items` which you could see in the Azure portal was the case. We also define it as `direction` having the value `in`. This means that this will set up the connection for us and whatever object we are given will contain the data we need.
There is one more thing here `connectionStringSetting` pointing to the value `CosmosDB`, now this is an AppSetting we set up in our Azure Functions app project. We haven't deployed it to Azure yet so we need to store this somewhere, for now, that somewhere is in the file `local.settings.json`. It should look like this currently:

```json
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "CosmosDB": "[connection string to our database]"
  }
}
```
You need to go to the portal and our created database, click the tab menu `Keys` and copy the value in the field `Primary Connection String` and then set it to the value of above key `CosmosDB`. 

### Additional configuration

We are not quite done there I'm afraid. There are two more things we need to do:

1. **Dependencies**, set up dependencies to be installed
2. **Storage account**, set up a storage account

The first bit we solve by opening up the file `host.json` and ensure it has the following content:

```json
{
  "version": "2.0",
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[1.*, 2.0.0)"
  }
}
```

The key and value for `extensionBundle` instruct Azure that it should be installing all needed libraries so we can talk to queues, databases and pretty much all cool things we can integrate our Azure Function App with as input and output bindings.

The second and last thing we need to do is to create a storage account. We can easily do so in the portal by clicking `Add Resource`, type `Storage Account` and follow the instructions. Then we need to obtain the connection string and we need to add an entry to the file `local.settings.json`, like so:

```json
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "[storage account connection string]",
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "CosmosDB": "[database connection string]"
  }
}
```

### Write some code

At this point, we want to write some code in our `ProductsGet` functions. So we need to edit `ProductsGet/index.js` to say the following:

```js
module.exports = function (context, req) {
  for(var i =0; i< context.bindings.productDocument.length; i++) {
      let product = context.bindings.productDocument[i];
      context.log('id', product.id); 
      context.log('name', product.name);
  }

  context.res = {
      // status: 200, /* Defaults to 200 */
      body: "Ran ProductsGet"
  };
};
```
Looking at code above we see that `context.binding.productDoucment` is containing a list of our `Items`. We iterate that list in the code and print out `id` and `name`. Because of configuration like this in `function.json`:

```json
{
  "name": "productDocument",
  "type": "cosmosDB",
  "databaseName": "ToDoList",
  "collectionName": "Items",
  "createIfNotExists": true,
  "connectionStringSetting": "CosmosDB",
  "direction": "in"
}
```
we establish a connection to our Azure Cosmos DB database and a specific collection `Items` and ensure to create a handle `productDocument`. Imagine having to write the connect to database code yourself, not fun right?

### Deploy and test it out

Ok, next step is to deploy it. To deploy it we need to do two things:

1. **Deploy the Azure Function app**, this is as simple as clicking a button in VS Code
2. **Deploy the local app settings** to Azure, this is needed to ensure our AppSettings in Azure correctly points out our Azure Cosmos DB database but also our storage account.

Let's start with the deploy part. Ensure you have the following extension installed in VS Code:

![](https://thepracticaldev.s3.amazonaws.com/i/k2kwed7fygebkmia7pte.png)

This will enable you to easily deploy anything to Azure. We started this article talking about another extension namely `Azure Functions`. Ensure you have them both installed and life will be a lot simpler. 

Now as for the deployment part. Start by clicking the highlighted Azure icon below 
![](https://thepracticaldev.s3.amazonaws.com/i/c8y12pttws3dood1l76d.png)

Then we come here:

![](https://thepracticaldev.s3.amazonaws.com/i/couf0kfd3ilklg8yjzed.png)

Indicated at the top right is an icon looking like a flash. Clicking that will deploy the app to Azure. 

Afterward, it will become part of the list below the flash icon. It's also where we would go to redeploy changes.

The last step is to ensure we upload all the local app settings to Azure. To do that we need to talk our deployed Azure Function App and right-click it and choose to upload them. It should look like so:

![](https://thepracticaldev.s3.amazonaws.com/i/ubjmhjteub624nkmoyi9.png)

At this point, the app should actually work. So lets head to the Azure Portal and try it out:

![](https://thepracticaldev.s3.amazonaws.com/i/fncix588u4dt2bha0l26.png)

Just click on the correct function `ProductsGet` then click `Run`. This will produce a terminal window below that will print the following:

![](https://thepracticaldev.s3.amazonaws.com/i/dek7ma9vjobcxf0sl9ue.png)

As you can see from the above image it is reading from the Azure Cosmos DB database.

Awesome right, we have a working connection. Now to talk the remaining operations.

## Adding remaining operations

So far we have been reading so how to support these additional operations? Well, we need to configure each `function.json` and give it the correct type of configuration and we, of course, need to go into each `index.js` and add the necessary code to either Create or Update.

### Supporting creation

So far we have been supporting how to read data from our database. We accomplished that by creating a binding that had a `direction` value of `in` and we also needed to point out our database and what collection to read from.

Creating something is about creating a binding with `direction` having the value `out`. This gives us a handle that we can add data to.

Let's start with the configuration part. In the file `ProductsCreate/function.json` we add the following entry to our bindings array:

```json
 {
  "name": "productDocument",
  "type": "cosmosDB",
  "databaseName": "ToDoList",
  "collectionName": "Items",
  "createIfNotExists": true,
  "connectionStringSetting": "CosmosDB",
  "direction": "out"
}
```
Ok that sets us up nicely so we can focus on the second step, adding code to `ProductsCreate/index.js`:

```js
module.exports = function (context, req) {
     const { id, name } = req.body;

    // creating doc
    context.bindings.productDocument = JSON.stringify({
        id: id,
        name: name
    });

    // saving doc
    context.done();
};
```

Note how the configuration value for they key `name` in `function.json` matches `context.bindings.productDocument`. What we do then is to assign an object to `productDocument`:

```js
context.bindings.productDocument = JSON.stringify({
  id: id,
  name: name
});
```

Above we are creating the record we want to be inserted. To actually *do the save* we end it all with the command `context.done()`

We don't believe this until we tried it right? The first thing we need to do is to redeploy our project to Azure. Because we deployed it once already, it's super simple to redeploy. Click the Azure extension on the left panel then right-click your Azure Functions app project and select `Deploy to Function App` like below: 

![](https://thepracticaldev.s3.amazonaws.com/i/jguzbglb16mmtd12sshb.png)

This will redeploy it all. Wait for it to finish. 

> Done? good let's continue

For this one, let's head to the Azure Portal and test it (you can use cURL or any client that supports sending REST calls). 

In the portal we want to select our function and click the `Test` tab on the right:

![](https://thepracticaldev.s3.amazonaws.com/i/chl9ux18riuyeu59yb64.png)

Now enter a request like so:

![](https://thepracticaldev.s3.amazonaws.com/i/mpxplv3jzash64tpy0eg.png)

Next step is to click the `Run` button. We should be getting a result like the below

![](https://thepracticaldev.s3.amazonaws.com/i/dnqc2j91l1t49nhju2he.png)

To really verify that this worked, head to the resource page for your database and see if you have a third record:

![](https://thepracticaldev.s3.amazonaws.com/i/qqdjwpllrct2w7t0t30d.png)

There it is ! :)

That's it for creation, let's talk about updating next.

### Supporting update

Updating a record is a different matter. We need to support two bindings. Why is that you ask?

Well, we need a binding of type `in` so we can retrieve the record we need.

Then we need a second `out` binding to actually *replace* the record.

> Hmm ok, show me

Ok then, bindings first, they should look like this:

```json
{
  "name": "productDocument",
  "type": "cosmosDB",
  "databaseName": "ToDoList",
  "collectionName": "Items",
  "createIfNotExists": true,
  "connectionStringSetting": "CosmosDB",
  "direction": "out"
},
{
  "name": "productDocumentsIn",
  "type": "cosmosDB",
  "databaseName": "ToDoList",
  "collectionName": "Items",
  "createIfNotExists": true,
  "connectionStringSetting": "CosmosDB",
  "direction": "in"
}
```

now to the code:

```js
module.exports = function (context, req) {
    const {
        id,
        name
    } = req.body;

    // or you could limit the in to only be one doc
    const foundDoc = context.bindings.productDocumentsIn.find(p => p.id == id);

    // do the update
    context.bindings.productDocument = foundDoc;
    context.bindings.productDocument.name = name;

    context.done();

    context.res = {
        // status: 200, /* Defaults to 200 */
        body: "Record updated"
    };
};
```

What we can see is how we first retrieve the record from our input binding `productDocumentsIn` and assign it to the variable `foundDoc`. Next thing we do is assign `foundDoc` to our `out` handle found on `context.bindings.productDocument`. We do this to ensure we don't lose any values on this record should or values on the body only represent a partial update. Next thing we do is take the `name` that came with our `body` and apply that, like so `context.bindings.productDocument.name = name` and of course we finish that off with a `context.done()`.

That's it, that is how we support updating.

## Summary

We started off by creating a Azure Cosmos DB database. Then we put some data in there. Next, we created some serverless functions. Thereafter we learned about *bindings* and how those could save us time when it came to creating a connection towards our database. Thanks to the bindings we ended up writing quite little code to support reading and writing. 

How about you try this too? :)