JavaScript: Store data in MongoDB with Azure Function
Create an Azure Function API to store data with Mongoose API into Azure Cosmos DB, then deploy the Function application to the Azure cloud for hosting with a public HTTP endpoint.
Full source code for this Azure Function app:
Prepare your development environment
Install the following software:
- Create a free Azure subscription
- Install Node.js LTS - this article was written and tested with Node.js 14
- Install Visual Studio Code and use the following extensions:
The following software is installed as part of the tutorial later:
- Azure Functions Core Tools - to develop, run, and debug Azure Functions on your local workstation
1. Sign in to Azure in Visual Studio Code
If you already use the Azure service extensions, you should already be logged in and can skip this step.
Once you've installed an Azure service extension in Visual Studio Code, you need to sign into your Azure account.
In Visual Studio Code, open the Azure explorer by selecting the Azure icon in the primary side bar or use the keyboard shortcut (Shift + Alt + A).
In the Resources section, select Sign in to Azure, and follow the prompts.
After signing in, verify that the email address of your Azure account appears in the Status Bar and your subscription(s) appears in the Azure explorer:
2. Create an Azure resource group
A resource group is a region-based collection of resources. By creating a resource group, then creating resources in that group, at the end of the tutorial, you can delete the resource group without having to delete each resource individually.
In Visual Studio Code, open the Azure explorer by selecting the Azure icon in the primary side bar or use the keyboard shortcut (Shift + Alt + A).
Find your subscription under Resources and select the + icon then select Create Resource Group.
Use the following table to complete the prompts:
Prompt Value Enter the name of the new resource group. cosmosdb-mongodb-function-resource-group
Select a location for your new resources. Select a geographical region close to you.
3. Create the local Functions app
Create a local Azure Functions (serverless) application that contains an HTTP trigger function.
In Visual Studio Code, open the Azure explorer by selecting the Azure icon in the primary side bar or use the keyboard shortcut (Shift + Alt + A).
In the Workspace section, select the + then select Create function.
A pop-up displays asking you if you want to Create new project?. Select Yes.
Use the following table to finish creating the local Azure Function project:
Prompt Value Notes Select a language TypeScript Select a template for your project's first function HTTP Trigger API is invoked with an HTTP request. Provide a function name category
API route is /api/category
Authorization Level Function This locks the remote API to requests that pass the function key with the request. While developing locally, you won't need the function key. When Visual Studio Code completes creation of the project, use the File explorer, Ctrl + Shift + D, to view your project with a folder named for the function, category with three files:
Filename Description index.ts The source code that responds to the HTTP request. function.json The binding configuration for the HTTP trigger. sample.dat A placeholder data file to demonstrate that you can have other files in the folder. You can delete this file, if desired, as it's not used in this tutorial. In Visual Studio Code, open an integrated bash terminal, Ctrl + ` and install the Azure Function app dependencies:
npm install
Add the Azure Function core tools package, required to run the Azure Function app locally:
npm install --global azure-functions-core-tools
In the
./category/index.ts
file, add a newcontext.log
message to print the name to the function's log, highlighted in the following code:import { AzureFunction, Context, HttpRequest } from "@azure/functions" const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> { context.log('HTTP trigger function processed a request.'); const name = (req.query.name || (req.body && req.body.name)); context.log(`*** HTTPExample name: ${name}`); const responseMessage = name ? "Hello, " + name + ". This HTTP triggered function executed successfully." : "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."; context.res = { // status: 200, /* Defaults to 200 */ body: responseMessage }; }; export default httpTrigger;
4. Run the local serverless function
Run the Azure Functions project locally to test it before deploying to Azure.
In Visual Studio Code, open the
./category/index.ts
file, set a break point on the finalcontext.res
block, at the end of the function.In Visual Studio Code, press F5 to launch the debugger and attach to the Azure Functions host.
You could also use the Debug > Start Debugging menu command.
Output from the Functions Core tools appears in the Terminal panel.
In Visual Studio Code, open the Azure explorer by selecting the Azure icon in the primary side bar or use the keyboard shortcut (Shift + Alt + A).
In the Workspace section, find and expand the Local Project -> Functions -> category.
Right-click the function name, category, then select Copy Function Url.
In your browser, paste the URL, then add
?name=YOUR-NAME
to the end of URL, replacingYOUR-NAME
with your name:Because the function is running locally, your local API doesn't need the function key to work successfully.
In VS Code, when the breakpoint hits, review the variables and call stack. Step over the break point to let the function complete.
Optionally, to see the entire HTTP response, use the following cURL command in the terminal:
curl http://localhost:7071/api/category?name=john --verbose
The response is:
* Trying ::1:7071... * Trying 127.0.0.1:7071... * Connected to localhost (127.0.0.1) port 7071 (#0) > GET /api/category?name=john HTTP/1.1 > Host: localhost:7071 > User-Agent: curl/7.75.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Date: Tue, 21 Sep 2021 17:35:05 GMT < Content-Type: text/plain; charset=utf-8 < Server: Kestrel < Transfer-Encoding: chunked < Request-Context: appId=cid-v1:e981b763-c455-4e32-852c-73765b048a0f < Hello, john. This HTTP triggered function executed successfully.* Connection #0 to host localhost left intact
In VS Code, stop the debugger, Shift + F5.
5. Create the Azure Function app in Visual Studio Code
In this section, you create a function app and related resources in your Azure subscription.
Choose the Azure icon in the Activity bar. Then in the Resources area, select the + icon and choose the Create Function App in Azure option.
Provide the following information at the prompts:
Prompt Selection Select subscription Choose the subscription to use. You won't see this prompt when you have only one subscription visible under Resources. Enter a globally unique name for the function app Type a name that is valid in a URL path. The name you type is validated to make sure that it's unique in Azure Functions. Select a runtime stack Choose the language version on which you've been running locally. Select a location for new resources For better performance, choose a region near you. The extension shows the status of individual resources as they're being created in Azure in the Azure: Activity Log panel.
6. Deploy the Azure Function app to Azure in Visual Studio Code
Important
Deploying to an existing function app always overwrites the contents of that app in Azure.
- Choose the Azure icon in the Activity bar, then in the Resources area, right-click your function app resource and select the Deploy to function app button.
- If you're asked if you're sure you want to deploy, select Deploy.
- After deployment completes, a notification displays with severals options. Select View Output to view the results. If you miss the notification, select the bell icon in the lower right corner to see it again.
7. Run the remote serverless function
In Visual Studio Code, open the Azure explorer by selecting the Azure icon in the primary side bar or use the keyboard shortcut (Shift + Alt + A).
In the Resources section, expand your Azure Function app resource. Right-click the function name,
category
, in the Functions node, and select Copy Function Url:Paste the URL into a browser. The URL includes the function key,
code
, as a query parameter.Append a querystring name/value pair,
&name=YOUR-NAME
, to the URL. The browser shows the successful function running in the cloud.Now remove the
code=
querystring parameter from the URL and submit the URL in the browser again. This simulates an unauthorized request to your secured API.Review the streaming log in Visual Studio Code to find your
context.log
output.
8. Add Azure Cosmos DB for MongoDB API integration
Azure Cosmos DB provides a MongoDB API to provide a familiar integration point.
In Visual Studio Code, open the Azure explorer by selecting the Azure icon in the primary side bar or use the keyboard shortcut (Shift + Alt + A).
In the Resources section, select the + then select Create Database Server. Use the following table to complete the prompts to create a new Azure Cosmos DB resource.
Prompt Value Notes Select an Azure Database Server Azure Cosmos DB for MongoDB API Provide an Azure Cosmos DB account name. cosmosdb-mongodb-database
The name becomes part of the API's URL. Select a capacity model. Provisioned Throughput Select a resource group for new resources. cosmosdb-mongodb-function-resource-group
Select or create a resource group Select a location for new resources. Select the recommended region. In a Visual Studio Code terminal, Ctrl + Shift + `, then install the npm package:
npm install mongoose
In Visual Studio Code, create a subdirectory named
lib
, create a file named./azure-cosmosdb-mongodb.ts
and copy the following code into it.import { Schema, model, connect } from "mongoose"; let db=null; const CategorySchema = new Schema( { categoryName: String }, { timestamps: true } ); const CategoryModel = model("Category", CategorySchema, "Bookstore"); export const init = async () => { if(!db) { db = await connect(process.env["CosmosDbConnectionString"]); } }; export const addItem = async (doc) => { const modelToInsert = new CategoryModel(); modelToInsert["categoryName"] = doc.name; return await modelToInsert.save(); }; export const findItemById = async (id) => { return await CategoryModel.findById(id); }; export const findItems = async (query = {}) => { return await CategoryModel.find({}); }; export const deleteItemById = async (id) => { return await CategoryModel.findByIdAndDelete(id); };
This file contains a simple mongoose schema for a Category container.
In Visual Studio Code, open the
./category/index.ts
file and replace the entire file's code with the following:import { AzureFunction, Context, HttpRequest } from "@azure/functions"; import * as db from "../lib/azure-cosmosdb-mongodb"; const httpTrigger: AzureFunction = async function ( context: Context, req: HttpRequest ): Promise<void> { try { let response = null; // create 1 db connection for all functions await db.init(); switch (req.method) { case "GET": if (req?.query.id || (req?.body && req?.body?.id)) { response = { documentResponse: await db.findItemById(req?.body?.id), }; } else { // allows empty query to return all items const dbQuery = req?.query?.dbQuery || (req?.body && req?.body?.dbQuery); response = { documentResponse: await db.findItems(dbQuery), }; } break; case "POST": if (req?.body?.document) { const insertOneResponse = await db.addItem(req?.body?.document); response = { documentResponse: insertOneResponse, }; } else { throw Error("No document found"); } break; case "DELETE": if (req?.query?.id || (req?.body && req?.body?.id)) { response = { documentResponse: await db.deleteItemById(req?.body?.id), }; } else { throw Error("No id found"); } break; default: throw Error(`${req.method} not allowed`) } context.res = { body: response, }; } catch (err) { context.log(`*** Error throw: ${JSON.stringify(err)}`); context.res = { status: 500, body: err, }; } }; export default httpTrigger;
In Visual Studio Code, open the
./category/function.json
file and change the methods property to include delete.{ "bindings": [ { "authLevel": "function", "type": "httpTrigger", "direction": "in", "name": "req", "methods": [ "get", "post", "delete" ] }, { "type": "http", "direction": "out", "name": "res" } ], "scriptFile": "../dist/category/index.js" }
9. Add remote Azure Cosmos DB database connection string to local Node.js serverless project
In Visual Studio Code, open the Azure explorer by selecting the Azure icon in the primary side bar or use the keyboard shortcut (Shift + Alt + A).
In the Resources section, right-click your Azure Cosmos DB database and select Copy Connection String.
Open the
./local.settings.json
file and add a new propertyCosmosDbConnectionString
and paste in the database connection string in as the value.{ "IsEncrypted": false, "Values": { "FUNCTIONS_WORKER_RUNTIME": "node", "CosmosDbConnectionString": "" } }
10. Use the Azure Function APIs
Add items to database with serverless API using cURL command
In Visual Studio Code, press F5 to launch the debugger and attach to the Azure Functions host.
Use the following cURL command in a new terminal, Ctrl + Shift + `, to add John to your database:
curl -X POST http://localhost:7071/api/category \ -H 'Content-Type: application/json' \ -d '{"document":{"name":"John"}}' --verbose
The response includes the new item's ID:
{ "documentResponse": { "_id": "614a45d97ccca62acd742550", "categoryName": "John", "createdAt": "2021-09-21T20:51:37.669Z", "updatedAt": "2021-09-21T20:51:37.669Z", "__v": 0 } }
Use the following curl command in the integrated bash terminal to add Sally to your database:
curl -X POST http://localhost:7071/api/category \ -H 'Content-Type: application/json' \ -d '{"document":{"name":"Sally"}}' --verbose
The response includes the new item's ID:
{ "documentResponse": { "_id": "614a45d97bbba62acd742550", "categoryName": "Sally", "createdAt": "2021-09-21T20:51:37.669Z", "updatedAt": "2021-09-21T20:51:37.669Z", "__v": 0 } }
Get all items from database with API
Use the following curl command to get all items from the database:
curl -X GET http://localhost:7071/api/category \ -H 'Content-Type: application/json' --verbose
The response includes the new item's ID:
{ "documentResponse": [ { "_id": "614a45d97ccca62acd742550", "categoryName": "John", "createdAt": "2021-09-21T20:51:25.288Z", "updatedAt": "2021-09-21T20:51:25.288Z", "__v": 0 }, { "_id": "614a45d97bbba62acd742550", "categoryName": "Sally", "createdAt": "2021-09-21T20:51:37.669Z", "updatedAt": "2021-09-21T20:51:37.669Z", "__v": 0 } ] }
View all data with VSCode extension for Azure Cosmos DB
In Visual Studio Code, open the Azure explorer by selecting the Azure icon in the primary side bar or use the keyboard shortcut (Shift + Alt + A).
In the Resources section, right-click your Azure Cosmos DB database and select Refresh.
Expand the test database and Bookstore collection node's to view the documents.
Select one of the items listed to view the data in the Azure Cosmos DB instance.
Get one item from the database with API
Use the following curl command to get one item from the database. Replace
DOCUMENT_ID
with one of the IDs from a previous step's response:curl -X GET http://localhost:7071/api/category \ -H 'Content-Type: application/json' \ -d '{"id":"DOCUMENT_ID"}' --verbose
The response includes the new item's ID:
{ "documentResponse": { "_id": "614a45cd7ccca62acd74254e", "categoryName": "John", "createdAt": "2021-09-21T20:51:25.288Z", "updatedAt": "2021-09-21T20:51:25.288Z", "__v": 0 } }
Return to the Database section of the Azure Explorer in Visual Studio Code, right-click on your Azure Cosmos DB and select Refresh to verify that the item was removed from your cloud resource.
Delete one item from the database with API
Use the following curl command to delete one item from the database. Replace
DOCUMENT_ID
with one of the IDs from a previous step's response:curl -X DELETE http://localhost:7071/api/category \ -H 'Content-Type: application/json' \ -d '{"id":"DOCUMENT_ID"}' --verbose
The response includes the new item's ID:
{ "documentResponse": { "_id": "614a45cd7ccca62acd74254e", "categoryName": "John", "createdAt": "2021-09-21T20:51:25.288Z", "updatedAt": "2021-09-21T20:51:25.288Z", "__v": 0 } }
In VS Code, stop the debugger, Shift + F5.
11. Redeploy the function app to include database code
In Visual Studio Code, open the Azure explorer by selecting the Azure icon in the primary side bar or use the keyboard shortcut (Shift + Alt + A).
In the Resources section, right-click your Azure Function app and select Deploy to Function App.
In the pop-up asking if you're sure you want to deploy, select Deploy.
Wait until deployment completes before continuing.
12. Add Azure Cosmos DB database connection string to remote Azure Function app
In Visual Studio Code, open the Azure explorer by selecting the Azure icon in the primary side bar or use the keyboard shortcut (Shift + Alt + A).
In the Resources section, find your Azure Cosmos DB instance. Right-click the resource and select Copy Connection String.
In the same Resources section, find your Function App and expand the node.
Right-click on Application Settings and select Add New Setting.
Enter the app setting name,
CosmosDbConnectionString
and press enter.Paste the value you copied and press enter.
13. Use cloud-based Azure Function
Still in the Azure Explorer, in the Functions area, selects and expands your function then the Functions node, which lists the API, category.
Right-click on the category item and select Copy Function Url.
Use the following cURL commands, and replace YOUR-FUNCTION-URL. Run each command in a terminal in order.
curl -X POST YOUR-FUNCTION-URL \ -H 'Content-Type: application/json' \ -d '{"document":{"name":"John"}}' --verbose
curl -X POST YOUR-FUNCTION-URL \ -H 'Content-Type: application/json' \ -d '{"document":{"name":"Sally"}}' --verbose
curl -X GET YOUR-FUNCTION-URL \ -H 'Content-Type: application/json' --verbose
Use the following cURL commands, and replace YOUR-FUNCTION-URL and DOCUMENT_ID with an ID from the previous command. Run each command in a terminal in order.
curl -X GET YOUR-FUNCTION-URL \ -H 'Content-Type: application/json' \ -d '{"id":"DOCUMENT_ID"}' --verbose
curl -X DELETE YOUR-FUNCTION-URL \ -H 'Content-Type: application/json' \ -d '{"id":"DOCUMENT_ID"}' --verbose
14. Query your Azure Function logs
To search the logs, use the Azure portal.
In Visual Studio Code, select the Azure Explorer, then under Functions, right-click on your function app, then select Open in Portal.
This opens the Azure portal to your Azure Function.
From Settings, select Application Insights, then select View Application Insights data.
This link takes you to your separate metrics resource created for you when you created your Azure Function with Visual Studio Code.
From the Monitoring section, select Logs. If a Queries pop-up window appears, select the X in the top-right corner of the pop-up to close it.
In the New Query 1 pane, on the Tables tab, double-click the traces table.
This enters the Kusto query,
traces
into the query window.Edit the query to search for the custom logs:
traces | where message startswith "***"
Select Run.
If the log doesn't display any results, it may be because there's a few minute delay between the HTTP request to the Azure Function and the log availability in Kusto. Wait a few minutes and run the query again.
You didn't need to do anything extra to get this logging information:
- The code used the
context.log
function provided by the Function framework. By usingcontext
, instead ofconsole
, your logging can be filtered to the specific individual function. This is useful if your Function app has many functions. - The Function app added Application Insights for you.
- The Kusto Query tool is included in the Azure portal.
- You can select
traces
instead of having to learn to write a Kusto query to get even the minimum information from your logs.
- The code used the
Clean up resources
Remove the resources created in this procedure when you're done using them. In the following procedure, replace YOUR-RESOURCE-GROUP-NAME
with your own resource group name.
- In Visual Studio Code, still in the Azure explorer (Shift + Alt + A).
- In the Resources contextual toolbar, select Group by.
- In the list of group-by choices, select Group by Resource Group.
- Right-click on your resource group and select Delete Resource Group.
Next steps
Learn more about Azure Functions:
- Official YouTube Channel – Azure Functions
- Video: Migrating Your API to Serverless using Azure Functions - YouTube
- Azure Functions JavaScript developer guide
- Securing Azure Functions
Check out the other Azure extensions:
- Azure Tools
- Azure Databases
- Azure Storage
- Azure Functions
- Docker Tools
- Azure CLI Tools
- Azure Resource Manager tools
To learn more about working with Azure using Node.js, visit the resources below:
Feedback
Submit and view feedback for