Tutorial: Compilación de una aplicación web de Node.js mediante el SDK de JavaScript para administrar una cuenta de la API de NoSQL en Azure Cosmos DB
SE APLICA A: NoSQL
Como desarrollador, puede que tenga aplicaciones que usan datos de documentos NoSQL. Puede usar una cuenta de la API de NoSQL en Azure Cosmos DB para almacenar los datos de este documento y acceder a ellos. En este tutorial de Node.js se muestra cómo almacenar datos y acceder a ellos desde una cuenta de API para NoSQL en Azure Cosmos DB. En el tutorial se usa una aplicación Node.js Express hospedada en la característica Web Apps de Microsoft Azure App Service. En este tutorial, creará una aplicación basada en web (aplicación de tareas pendientes), que le permite crear, recuperar y completar tareas. Las tareas se almacenan como documentos JSON en Azure Cosmos DB.
En este tutorial se muestra cómo crear una cuenta de la API de NoSQL en Azure Cosmos DB mediante Azure Portal. Sin una tarjeta de crédito o una suscripción de Azure, puede hacer lo siguiente:
- Configure una cuenta gratuita de prueba de Azure Cosmos DB.
- Compile y ejecute una aplicación web que se base en el SDK de Node.js para crear una base de datos y un contenedor.
- Agregar elementos al contenedor.
En este tutorial se usa la versión 3.0 del SDK de JavaScript y se describen las siguientes tareas:
- Creación de una cuenta de Azure Cosmos DB
- Creación de una aplicación Node.js
- Conexión de una aplicación a Azure Cosmos DB
- Ejecución e implementación de la aplicación en Azure
Prerrequisitos
Antes de seguir las instrucciones del presente artículo, asegúrese de tener los siguientes recursos:
Si no tiene una suscripción de Azure ni una tarjeta de crédito, puede configurar una cuenta gratuita de prueba de Azure Cosmos DB.
Puede probar gratis Azure Cosmos DB sin una suscripción de Azure, de forma gratuita y sin compromiso. Como alternativa, puede crear una cuenta de nivel gratis de Azure Cosmos DB, con las primeras 1000 RU/s y 25 GB de almacenamiento de forma gratuita. También puede usar el emulador de Azure Cosmos DB con un identificador URI
https://localhost:8081
. Para obtener la clave que se va a usar con el emulador, consulte Autenticación de solicitudes.Node.js, versión 6.10 o posterior.
Express Generator (puede instalar Express mediante
npm install express-generator -g
)Instale Git en la estación de trabajo local.
Creación de una cuenta de Azure Cosmos DB
Para comenzar, cree una cuenta de Azure Cosmos DB. Si ya tiene una cuenta o si usa el emulador de Azure Cosmos DB en este tutorial, puede ir directamente a la Creación de una nueva aplicación Node.js.
En el menú de Azure Portal o en la página principal, seleccione Crear un recurso.
Busque Azure Cosmos DB. Seleccione Crear>Azure Cosmos DB.
En la página Crear una cuenta de Azure Cosmos DB, seleccione la opción Crear en la sección Azure Cosmos DB for NoSQL.
Azure Cosmos DB proporciona varias API:
- NoSQL, para datos de documento
- PostgreSQL
- MongoDB, para datos de documento
- Apache Cassandra
- Tabla
- Apache Gremlin, para datos de grafo
Para obtener más información sobre la API para NoSQL, consulte Bienvenido a Azure Cosmos DB.
En la página Crear una cuenta de Azure Cosmos DB, especifique la configuración básica de la nueva cuenta de Azure Cosmos DB.
Configuración valor Descripción Subscription Nombre de suscripción Seleccione la suscripción de Azure que quiere usar para esta cuenta de Azure Cosmos DB. Grupo de recursos Definición de un nombre de grupo de recursos Seleccione un grupo de recursos o seleccione Crear nuevo y escriba un nombre único para el grupo de recursos nuevo. Nombre de cuenta Un nombre único Escriba un nombre para identificar la cuenta de Azure Cosmos DB. Dado que documents.azure.com se anexa al nombre que se proporciona para crear el identificador URI, debe usar un nombre único. El nombre solo puede contener letras minúsculas, números y el carácter de guion (-). Debe tener entre 3 y 44 caracteres. Location Región más cercana a los usuarios Seleccione una ubicación geográfica para hospedar la cuenta de Azure Cosmos DB. Use la ubicación más cercana a los usuarios para que puedan acceder de la forma más rápida posible a los datos. Capacity mode (Modo de capacidad) Rendimiento aprovisionado o Sin servidor Seleccione Provisioned throughput (Rendimiento aprovisionado) para crear una cuenta en modo de rendimiento aprovisionado. Seleccione Serverless (Sin servidor) para crear una cuenta en modo sin servidor. Aplicar el descuento del nivel Gratis de Azure Cosmos DB Aplicar o No aplicar Con el nivel Gratis de Azure Cosmos DB, recibe los primeros 1000 RU/s y 25 GB de almacenamiento gratis en una cuenta. Más información acerca del nivel Gratis. Límite del rendimiento total de la cuenta Seleccionado o no Limite la cantidad total de rendimiento que se puede aprovisionar en esta cuenta. Este límite evita cargos inesperados relacionados con el rendimiento aprovisionado. Puede actualizar o quitar este límite después de crear la cuenta. Puede tener una cuenta de Azure Cosmos DB de nivel gratis por cada suscripción de Azure y debe optar por recibirla al crear la cuenta. Si no ve la opción para aplicar el descuento por nivel Gratis, significa que el nivel Gratis ya se habilitó en otra cuenta de la suscripción.
Nota
Las siguientes opciones no están disponibles si selecciona Serverless (Sin servidor) en Capacity mode (Modo de capacidad):
- Aplicación de descuento por nivel Gratis
- Límite del rendimiento total de la cuenta
En la pestaña Distribución global, configure los detalles siguientes. Puede dejar los valores predeterminados para este inicio rápido:
Configuración valor Descripción Redundancia geográfica Deshabilitar Habilite o deshabilite la distribución global en su cuenta. Para ello, debe emparejar su región con una región de par. Puede agregar más regiones a su cuenta más adelante. Escrituras en varias regiones Deshabilitar La funcionalidad de escrituras en varias regiones le permite aprovechar el rendimiento aprovisionado para sus bases de datos y contenedores de todo el mundo. Zonas de disponibilidad Deshabilitar Las zonas de disponibilidad le ayudan a mejorar aún más la disponibilidad y la resistencia de una aplicación. Nota
Las siguientes opciones no están disponibles si selecciona Sin servidor en Modo de capacidad en la página anterior Básico:
- Redundancia geográfica
- Escrituras en varias regiones
De manera opcional, puede configurar más detalles en las pestañas siguientes:
- Funciones de red. Configure el acceso desde una red virtual.
- Directiva de copia de seguridad. Configure una directiva de copia de seguridad periódica o continua.
- Cifrado. Use una clave administrada por el servicio o una clave administrada por el cliente.
- Etiquetas. Las etiquetas son pares nombre-valor que permiten categorizar los recursos y ver una facturación consolidada mediante la aplicación de la misma etiqueta en varios recursos y grupos de recursos.
Seleccione Revisar + crear.
Revise la configuración de la cuenta y seleccione Crear. La operación de creación de la cuenta tarda unos minutos. Espere hasta que la página del portal muestre Se completó la implementación .
Seleccione Ir al recurso para ir a la página de la cuenta de Azure Cosmos DB.
Vaya a la página de la cuenta de Azure Cosmos DB y seleccione Claves. Copie los valores que se van a usar en la aplicación web que creará a continuación.
Creación de una aplicación Node.js
Ahora, aprenderemos a crear un proyecto Node.js básico de Hola mundo usando el marco Express.
Abra su terminal favorito como, por ejemplo, el símbolo del sistema de Node.js.
Navegue hasta el directorio en el que desea almacenar la nueva aplicación.
Use Express Generator para generar una nueva aplicación denominada todo.
express todo
Abra el directorio todo e instale las dependencias.
cd todo npm install
Ejecute la nueva aplicación.
npm start
Para ver la nueva aplicación en un explorador, vaya a
http://localhost:3000
.Para detener la aplicación, use CTRL+C en la ventana del terminal y seleccione y para finalizar el trabajo por lotes.
Instalación de los módulos necesarios
El archivo package.json es uno de los archivos creados en la raíz del proyecto. Este archivo contiene una lista de módulos adicionales necesarios para una aplicación Node.js. Cuando implemente esta aplicación en Azure, este archivo se usará para determinar qué módulos se deben instalar en Azure para ofrecer respaldo a su aplicación. Instale dos paquetes más para este tutorial.
Instale el módulo @azure/cosmos mediante npm.
npm install @azure/cosmos
Conexión de la aplicación Node.js a Azure Cosmos DB
Después de completar la configuración inicial y los ajustes, aprenda a escribir el código que requiere la aplicación de tareas pendientes para comunicarse con Azure Cosmos DB.
Creación del modelo
En la raíz del directorio del proyecto, cree un nuevo directorio con el nombre models.
En el directorio models, cree un archivo nuevo con el nombre taskDao.js. Este archivo contiene el código necesario para crear la base de datos y el contenedor. También define los métodos para leer, actualizar, crear y encontrar tareas en Azure Cosmos DB.
Copie el código siguiente en el archivo 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
Guarde y cierre el archivo taskDao.js .
Crear el controlador
En el directorio routes del nuevo proyecto, cree un nuevo archivo denominado tasklist.js.
Agregue el siguiente código a tasklist.js. Este código carga los módulos CosmosClient y async, que utiliza tasklist.js. Este código también define la clase TaskList, que pasa como una instancia del objeto TaskDao que definimos anteriormente:
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;
Guarde y cierre el archivo tasklist.js .
Agregar config.js
En la raíz del directorio del proyecto, cree un nuevo archivo con el nombre config.js.
Agregue el código siguiente al archivo config.js. Este código define las opciones de configuración y los valores necesarios para nuestra aplicación.
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;
En el archivo config.js, actualice los valores de HOST y AUTH_KEY con los valores de la página de Claves de la cuenta de Azure Cosmos DB en Azure Portal.
Guarde y cierre el archivo config.js .
Modificar app.js
En el directorio del proyecto, abra el archivo app.js . Este archivo se creó anteriormente, cuando se creó la aplicación web de Express.
Agregue el código siguiente al archivo app.js. Este código define el archivo de configuración que se va a utilizar y carga los valores en algunas variables que se utilizarán en las secciones siguientes.
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
Por último, guarde y cierre el archivo app.js.
Creación de una interfaz de usuario
Ahora vamos a crear la interfaz de usuario para que un usuario pueda interactuar con la aplicación. La aplicación Express que hemos creado en las secciones anteriores utiliza Jade como motor de vistas.
El archivo layout.jade del directorio views se utiliza como plantilla global para otros archivos .jade. En este paso, lo modificará para usar Bootstrap, que es un kit de herramientas que se usa para diseñar un sitio web.
Abra el archivo layout.jade que se encuentra en la carpeta views y reemplace el contenido por el código siguiente:
doctype html html head 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') body 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')
Este código indica al motor Jade que represente HTML para nuestra aplicación y que cree un bloque llamado content donde podemos especificar el diseño de nuestras páginas de contenido. Guarde y cierre este archivo layout.jade.
Abra el archivo index.jade, la vista usada por la aplicación. Reemplace el contenido del archivo por el código siguiente:
extends layout block content h1 #{title} br form(action="/completetask", method="post") table.table.table-striped.table-bordered tr td Name td Category td Date td Complete if (typeof tasks === "undefined") tr td else each task in tasks tr 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} td if(task.completed) input(type="checkbox", name="#{task.id}", value="#{!task.completed}", checked=task.completed) else input(type="checkbox", name="#{task.id}", value="#{!task.completed}", checked=task.completed) button.btn.btn-primary(type="submit") Update tasks hr form.well(action="/addtask", method="post") label Item Name: input(name="name", type="textbox") label Item Category: input(name="category", type="textbox") br button.btn(type="submit") Add item
Este código amplía el diseño y proporciona contenido para el marcador de posición content que vimos anteriormente en el archivo layout.jade. En este diseño, hemos creado dos formularios HTML.
El primer formulario contiene una tabla para los datos y un botón que permite actualizar los elementos mediante la publicación en el método /completeTask del controlador.
El segundo formulario contiene dos campos de entrada y un botón que permite crear un nuevo elemento publicando en el método /addtask del controlador, que es todo lo que necesita para que la aplicación funcione.
Ejecución de la aplicación de forma local
Ahora que compiló la aplicación, puede ejecutarla localmente con los pasos siguientes:
Para probar la aplicación en el equipo local, ejecute
npm start
en el terminal para iniciar la aplicación y, a continuación, actualice la páginahttp://localhost:3000
. La página ahora debería tener un aspecto similar al de la siguiente captura de pantalla:Sugerencia
Si recibe un error de la sangría en el archivo layout.jade o el archivo index.jade, asegúrese de que las dos primeras líneas de ambos archivos estén justificadas a la izquierda, sin espacios en blanco. Si hay espacios delante de las dos primeras líneas, quítelos, guarde ambos archivos y, a continuación, actualice la ventana del explorador.
Use los campos Nombre de elemento y Categoría de elemento para escribir una nueva tarea y, a continuación, seleccione Agregar elemento para crear un documento en Azure Cosmos DB con esas propiedades.
La página debería actualizarse para mostrar el elemento recién creado en la lista de tareas pendientes.
Para completar una tarea, active la casilla de la columna Completar y, a continuación, seleccione Actualizar tareas para actualizar el documento que ya ha creado y quitarlo de la vista.
Para detener la aplicación, presione CTRL+C en la ventana del terminal y, después, seleccione Y para finalizar el trabajo por lotes.
Implementación de la aplicación en App Service
Una vez que la aplicación de ejecuta correctamente de manera local, puede implementarla en Azure App Service. En el terminal, asegúrese de que se encuentra en el directorio todo de la aplicación. Implemente el código en la carpeta local (tareas pendientes) mediante el siguiente comando az webapp up:
az webapp up --sku F1 --name <app-name>
Reemplace <app_name> por un nombre que sea único en todo Azure (los caracteres válidos son a-z, 0-9 y "-"). Un buen patrón es usar una combinación del nombre de la empresa y un identificador de la aplicación. Para obtener más información sobre la implementación de aplicaciones, consulte el artículo Implementación de aplicaciones de Node.js en Azure.
El comando puede tardar unos minutos en completarse. El comando proporciona mensajes sobre la creación del grupo de recursos, el plan de App Service y el recurso de la aplicación, la configuración del registro y la implementación del archivo ZIP. El comando proporciona estos mensajes mientras se ejecuta. A continuación, proporciona una dirección URL para iniciar la aplicación en http://<app-name>.azurewebsites.net
, que es la dirección URL de la aplicación en Azure.
Limpieza de recursos
Cuando ya no necesite estos recursos, podrá eliminar el grupo de recursos, la cuenta de Azure Cosmos DB y todos los recursos relacionados. Para hacerlo, seleccione el grupo de recursos que usó en la cuenta de Azure Cosmos DB, seleccione Eliminar y confirme el nombre del grupo de recursos que se va a eliminar.
Pasos siguientes
Para ello, puede usar información sobre el clúster de bases de datos existente.