通过 npm 安装 @azure/cosmos 模板。
npm install @azure/cosmos
将 Node.js 应用程序连接到 Azure Cosmos DB
完成初始设置和配置后,了解如何编写待办事项应用程序与 Azure Cosmos DB 通信所需的代码。
在项目的根目录中,创建名为 models的新目录。
在 models 目录中,创建一个名为 taskDao.js 的新文件。 此文件包含创建数据库和容器所需的代码, 并定义在 Azure Cosmos DB 中读取、更新、创建和查找任务所需的方法。
将以下代码复制到“taskDao.js”文件中:
// @ts-check
const CosmosClient = require('@azure/cosmos').CosmosClient
const debug = require('debug')('todo:taskDao')
// For simplicity we'll set a constant partition key
const partitionKey = undefined
class TaskDao {
* Manages reading, adding, and updating Tasks in Azure Cosmos DB
* @param {CosmosClient} cosmosClient
* @param {string} databaseId
* @param {string} containerId
constructor(cosmosClient, databaseId, containerId) {
this.client = cosmosClient
this.databaseId = databaseId
this.collectionId = containerId
this.database = null
this.container = null
async init() {
debug('Setting up the database...')
const dbResponse = await this.client.databases.createIfNotExists({
id: this.databaseId
this.database = dbResponse.database
debug('Setting up the database...done!')
debug('Setting up the container...')
const coResponse = await this.database.containers.createIfNotExists({
id: this.collectionId
this.container = coResponse.container
debug('Setting up the container...done!')
async find(querySpec) {
debug('Querying for items from the database')
if (!this.container) {
throw new Error('Collection is not initialized.')
const { resources } = await this.container.items.query(querySpec).fetchAll()
return resources
async addItem(item) {
debug('Adding an item to the database')
item.date = Date.now()
item.completed = false
const { resource: doc } = await this.container.items.create(item)
return doc
async updateItem(itemId) {
debug('Update an item in the database')
const doc = await this.getItem(itemId)
doc.completed = true
const { resource: replaced } = await this.container
.item(itemId, partitionKey)
.replace(doc)
return replaced
async getItem(itemId) {
debug('Getting an item from the database')
const { resource } = await this.container.item(itemId, partitionKey).read()
return resource
module.exports = TaskDao
保存并关闭 taskDao.js 文件。
创建控制器
在项目的 routes 目录中,创建一个名为 tasklist.js 的新文件。
将以下代码添加到 tasklist.js。 此代码会加载 tasklist.js 使用的 CosmosClient 和 async 模块, 并定义 TaskList 类,该类作为我们之前定义的 TaskDao 对象的一个实例来传递:
const TaskDao = require("../models/TaskDao");
class TaskList {
* Handles the various APIs for displaying and managing tasks
* @param {TaskDao} taskDao
constructor(taskDao) {
this.taskDao = taskDao;
async showTasks(req, res) {
const querySpec = {
query: "SELECT * FROM root r WHERE r.completed=@completed",
parameters: [
name: "@completed",
value: false
const items = await this.taskDao.find(querySpec);
res.render("index", {
title: "My ToDo List ",
tasks: items
async addTask(req, res) {
const item = req.body;
await this.taskDao.addItem(item);
res.redirect("/");
async completeTask(req, res) {
const completedTasks = Object.keys(req.body);
const tasks = [];
completedTasks.forEach(task => {
tasks.push(this.taskDao.updateItem(task));
await Promise.all(tasks);
res.redirect("/");
module.exports = TaskList;
保存并关闭 tasklist.js 文件。
添加 config.js
在项目根目录中创建一个名为 config.js 的新文件。
将以下代码添加到 config.js 文件。 此代码会定义应用程序所需的配置设置和值。
const config = {};
config.host = process.env.HOST || "[the endpoint URI of your Azure Cosmos DB account]";
config.authKey =
process.env.AUTH_KEY || "[the PRIMARY KEY value of your Azure Cosmos DB account";
config.databaseId = "ToDoList";
config.containerId = "Items";
if (config.host.includes("https://localhost:")) {
console.log("Local environment detected");
console.log("WARNING: Disabled checking of self-signed certs. Do not have this code in production.");
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
console.log(`Go to http://localhost:${process.env.PORT || '3000'} to try the sample.`);
module.exports = config;
在 config.js 文件中,使用 Azure 门户 上 Azure Cosmos DB 帐户 密钥 页面中的值更新 HOST 和 AUTH_KEY 的值。
保存并关闭 config.js 文件。
修改 app.js
在项目目录中,打开 app.js 文件。 此文件早于 Express Web 应用程序创建。
将以下代码添加到 app.js 文件。 此代码定义要使用的配置文件,并将值加载到将在后续部分使用的一些变量中。
const CosmosClient = require('@azure/cosmos').CosmosClient
const config = require('./config')
const TaskList = require('./routes/tasklist')
const TaskDao = require('./models/taskDao')
const express = require('express')
const path = require('path')
const logger = require('morgan')
const cookieParser = require('cookie-parser')
const bodyParser = require('body-parser')
const app = express()
// view engine setup
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'jade')
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))
app.use(cookieParser())
app.use(express.static(path.join(__dirname, 'public')))
//Todo App:
const cosmosClient = new CosmosClient({
endpoint: config.host,
key: config.authKey
const taskDao = new TaskDao(cosmosClient, config.databaseId, config.containerId)
const taskList = new TaskList(taskDao)
taskDao
.init(err => {
console.error(err)
.catch(err => {
console.error(err)
console.error(
'Shutting down because there was an error settinig up the database.'
process.exit(1)
app.get('/', (req, res, next) => taskList.showTasks(req, res).catch(next))
app.post('/addtask', (req, res, next) => taskList.addTask(req, res).catch(next))
app.post('/completetask', (req, res, next) =>
taskList.completeTask(req, res).catch(next)
app.set('view engine', 'jade')
// catch 404 and forward to error handler
app.use(function(req, res, next) {
const err = new Error('Not Found')
err.status = 404
next(err)
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message
res.locals.error = req.app.get('env') === 'development' ? err : {}
// render the error page
res.status(err.status || 500)
res.render('error')
module.exports = app
最后,保存并关闭 app.js 文件。
生成用户界面
现在,生成用户界面,以便用户可以与应用程序交互。 你在前面部分创建的 Express 应用程序将 Jade 用作视图引擎。
views 目录中的 layout.jade 文件用作其他 .jade 文件的全局模板。 在此步骤中,你会对其进行修改以使用 Twitter Bootstrap(用于设计网站的工具包)。
打开 views 文件夹中的 layout.jade 文件,将内容替换为以下代码:
doctype html
title= title
link(rel='stylesheet', href='//ajax.aspnetcdn.com/ajax/bootstrap/3.3.2/css/bootstrap.min.css')
link(rel='stylesheet', href='/stylesheets/style.css')
nav.navbar.navbar-inverse.navbar-fixed-top
div.navbar-header
a.navbar-brand(href='#') My Tasks
block content
script(src='//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.2.min.js')
script(src='//ajax.aspnetcdn.com/ajax/bootstrap/3.3.2/bootstrap.min.js')
此代码会告知 Jade 引擎为应用程序呈现一些 HTML,并创建名为 content 的 块,可以在其中提供内容页面的布局。 保存并关闭 layout.jade 文件。
打开 index.jade 文件,即应用程序使用的视图。 将文件内容替换为以下代码:
extends layout
block content
h1 #{title}
form(action="/completetask", method="post")
table.table.table-striped.table-bordered
td Name
td Category
td Date
td Complete
if (typeof tasks === "undefined")
each task in tasks
td #{task.name}
td #{task.category}
- var date = new Date(task.date);
- var day = date.getDate();
- var month = date.getMonth() + 1;
- var year = date.getFullYear();
td #{month + "/" + day + "/" + year}
if(task.completed)
input(type="checkbox", name="#{task.id}", value="#{!task.completed}", checked=task.completed)
input(type="checkbox", name="#{task.id}", value="#{!task.completed}", checked=task.completed)
button.btn.btn-primary(type="submit") Update tasks
form.well(action="/addtask", method="post")
label Item Name:
input(name="name", type="textbox")
label Item Category:
input(name="category", type="textbox")
button.btn(type="submit") Add item
此代码会扩展布局,并为你曾在 layout.jade 文件中看到的 content 占位符提供内容。 在该布局中,你创建了两个 HTML 窗体。
第一个窗体包含一份数据表和一个按钮,允许发布到控制器的 /completeTask 方法,从而更新项。
第二个窗体包含两个输入字段和一个按钮,允许发布到控制器的 /addtask 方法以创建新项,这是应用程序正常运行所需的全部内容。
在本地运行应用程序
生成应用程序后,可以执行以下步骤以在本地运行该程序:
要在本地计算机上测试应用程序,请在终端中运行 npm start
以启动应用程序,然后刷新 http://localhost:3000
页面。 页面现在应如以下屏幕截图所示:
如果收到有关 layout.jade 文件或 index.jade 文件中缩进的错误,请确保这两个文件中的头两行都已左对齐,且没有空格。 如果头两行之前留有空格,请删除这些空格,将这两个文件保存,然后刷新浏览器窗口。
使用“项名称”和“项类别”字段输入新任务,然后选择“添加项”以在 Azure Cosmos DB 中创建具有这些属性的文档。
页面会更新以在待办事项列表中显示新建项。
要完成任务,请依次选择“完成”列中的复选框、“更新任务”以更新已创建的文档并将其从视图中删除。
要停止应用程序,请在终端窗口中按 CTRL+C,然后选择“y”以终止批处理作业。
将应用程序部署到应用服务
应用程序在本地成功以后,即可将其部署到 Azure 应用服务。 转到终端后,确保位于 todo 应用目录中。 使用以下 az webapp up 命令在本地文件夹(待办事项)中部署代码:
az webapp up --sku F1 --name <app-name>
将 <app_name> 替换为在整个 Azure 中均唯一的名称(有效字符为 a-z、0-9 和 -)。 良好的模式是结合使用公司名称和应用标识符。 要详细了解应用部署,请参阅 Azure 中的 Node.js 应用部署。
该命令可能需要几分钟时间才能完成。 该命令提供有关创建资源组、应用服务计划、应用资源、配置日志记录以及执行 ZIP 部署的消息。 该命令在运行时提供这些消息。 然后,它会提供一个 URL,用于在 http://<app-name>.azurewebsites.net
处启动应用,这是应用在 Azure 上的 URL。
不再需要这些资源时,可以删除资源组、Azure Cosmos DB 帐户和所有相关资源时。 为此,请选择用于 Azure Cosmos DB 帐户的资源组,接着选择“删除”,然后确认要删除的资源组的名称。
可以使用有关现有数据库群集的信息进行容量规划。
将非关系数据库中的 vCore 或 vCPU 数转换为 Azure Cosmos DB RU/s
使用 Azure Cosmos DB 容量规划器估算 RU/秒 (API for NoSQL)
使用 Xamarin 和 Azure Cosmos DB 构建移动应用程序
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:https://aka.ms/ContentUserFeedback。
提交和查看相关反馈