Tutorial: Creare un'app Web Node.js usando JavaScript SDK per gestire un account API per NoSQL in Azure Cosmos DB

APPLICABILE A: NoSQL

Gli sviluppatori possono avere applicazioni che usano dati documento NoSQL. È possibile usare un account API per NoSQL in Azure Cosmos DB per archiviare e accedere ai dati del documento. Questa esercitazione Node.js illustra come archiviare e accedere ai dati da un account API per NoSQL in Azure Cosmos DB. L'esercitazione usa un'applicazione Node.js Express ospitata nella funzionalità App Web del servizio app di Microsoft Azure. In questa esercitazione verrà creata un'applicazione basata sul Web (app Todo) che permette di creare, recuperare e completare attività. Le attività vengono memorizzate come documenti JSON in Azure Cosmos DB.

Questa esercitazione descrive come creare un account API per NoSQL in Azure Cosmos DB usando il portale di Azure. Senza una carta di credito o una sottoscrizione di Azure, è possibile:

  • Configurare un Account Azure Cosmos DB di prova gratuito.
  • Compilare ed eseguire un'app Web basata su Node.js SDK per creare un database e un contenitore.
  • Aggiungere elementi al contenitore.

Questa esercitazione usa JavaScript SDK versione 3.0 e illustra le seguenti attività:

  • Creare un account Azure Cosmos DB
  • Creare una nuova applicazione Node.js
  • Connettere l'applicazione ad Azure Cosmos DB
  • Eseguire e distribuire l'applicazione in Azure

Prerequisiti

Prima di seguire le istruzioni di questo articolo, verificare di disporre delle risorse seguenti:

Creare un account Azure Cosmos DB

Prima di tutto, creare un account Azure Cosmos DB. Se si ha già un account o si usa l'emulatore Azure Cosmos DB per questa esercitazione, è possibile passare direttamente a Creare una nuova applicazione MVC ASP.NET.

  1. Nel menu del portale di Azure o dalla pagina Home selezionare Crea una risorsa.

  2. Cercare Azure Cosmos DB. Selezionare Crea>Azure Cosmos DB.

  3. Nella pagina Creare un account Azure Cosmos DB, selezionare l'opzione Crea all'interno della sezione Azure Cosmos DB for NoSQL.

    Azure Cosmos DB offre diverse API:

    • NoSQL, per i dati del documento
    • PostgreSQL
    • MongoDB, per i dati del documento
    • Apache Cassandra
    • Tabella
    • Apache Gremlin, per i dati del grafo

    Per ulteriori informazioni sulla API per NoSQL, vedere Introduzione ad Azure Cosmos DB.

  4. Nella pagina Crea account Azure Cosmos DB, immettere le impostazioni base per il nuovo account Azure Cosmos DB.

    Impostazione valore Descrizione
    Abbonamento Nome della sottoscrizione Selezionare la sottoscrizione di Azure da usare per l'account Azure Cosmos DB.
    Gruppo di risorse Nome gruppo di risorse Selezionare un gruppo di risorse oppure fare clic su Crea nuovo, quindi immettere un nome univoco per il nuovo gruppo di risorse.
    Nome conto Un nome univoco Immettere un nome per identificare l'account Azure Cosmos DB. Dato che al nome specificato viene aggiunto documents.azure.com per creare l'URI, usare un nome univoco. Il nome può contenere solo lettere minuscole, numeri e il trattino (-). Deve essere di 3-44 caratteri.
    Ufficio Area più vicina ai propri utenti Selezionare una posizione geografica in cui ospitare l'account Azure Cosmos DB. Usare la località più vicina agli utenti per offrire loro la massima velocità di accesso ai dati.
    Modalità di capacità Velocità effettiva con provisioning o Serverless Selezionare Provisioning velocità effettiva per creare un account in modalità Provisioning velocità effettiva. Selezionare Serverless per creare un account in modalità Serverless.
    Applicare lo sconto in base al livello gratuito di Azure Cosmos DB Applicare o non applicare Il livello gratuito di Azure Cosmos DB offre i primi 1000 UR/sec e 25 GB di spazio di archiviazione gratuiti per account. Altre informazioni sul livello gratuito.
    Limitare la velocità effettiva totale dell'account Selezionato o non selezionato È possibile limitare la misura totale di velocità effettiva di provisioning in questo account. Questo limite impedisce addebiti imprevisti correlati alla velocità effettiva con provisioning. È possibile aggiornare o rimuovere questo limite dopo la creazione dell'account.

    È possibile avere al massimo un account Azure Cosmos DB di livello gratuito per ogni sottoscrizione di Azure ed è necessario acconsentire esplicitamente durante la creazione dell'account. Se l'opzione di applicare lo sconto per il livello gratuito non è visualizzata, significa che un altro account nella sottoscrizione è già stato abilitato per il livello gratuito.

    Screenshot shows the Create Azure Cosmos DB Account page.

    Nota

    Le opzioni seguenti non sono disponibili se si seleziona Serverless come modalità di capacità:

    • Applica sconto livello gratuito
    • Limitare la velocità effettiva totale dell'account
  5. Nella scheda Distribuzione globale configurare i dettagli seguenti. Per questa guida introduttiva, è possibile lasciare i valori predefiniti:

    Impostazione valore Descrizione
    Ridondanza geografica Disabilita Abilitare o disabilitare la distribuzione globale nell'account associando la propria area a un'altra area. È possibile aggiungere altre aree al proprio account in un secondo momento.
    Scritture in più aree Disabilita La funzionalità Scritture in più aree consente di sfruttare la velocità effettiva di cui è stato effettuato il provisioning per i database e i contenitori in tutto il mondo.
    Zone di disponibilità Disabilita Le zone di disponibilità consentono di migliorare ulteriormente la disponibilità e la resilienza dell'applicazione.

    Nota

    Le seguenti opzioni non sono disponibili se si seleziona Serverless come modalità di capacità nella pagina precedente Basic:

    • Ridondanza geografica
    • Scritture in più aree
  6. Facoltativamente, è possibile configurare altri dettagli nelle schede seguenti:

    • Reti. Configurare accesso da una rete virtuale.
    • Criteri di backup. Configurare criteri di backup periodici o continui.
    • Crittografia. Usare una chiave gestita dal servizio o una chiave gestita dal cliente.
    • Tag. I tag sono coppie nome-valore che consentono di classificare le risorse e visualizzare dati di fatturazione consolidati tramite l'applicazione dello stesso tag a più risorse e gruppi di risorse.
  7. Selezionare Rivedi e crea.

  8. Esaminare le impostazioni dell'account e quindi selezionare Crea. La creazione dell'account richiede alcuni minuti. Attendere che la pagina del portale visualizzi La distribuzione è stata completata.

    Screenshot shows that your deployment is complete.

  9. Selezionare Vai alla risorsa per passare alla pagina dell'account Azure Cosmos DB.

    Screenshot shows the Azure Cosmos DB account page.

Passare alla pagina dell'account Azure Cosmos DB e selezionare Chiavi. Copiare i valori da usare nell'applicazione Web che verrà creata successivamente.

Screenshot of the Azure portal with the Keys button highlighted on the Azure Cosmos DB account page

Creare una nuova applicazione Node.js

A questo punto, si imparerà come creare un progetto base Node.js Hello World usando il framework Express.

  1. Aprire il terminale preferito, ad esempio il prompt dei comandi di Node.js.

  2. Passare alla directory in cui si vuole archiviare la nuova applicazione.

  3. Usare il generatore di Express per generare una nuova applicazione denominata todo.

    express todo
    
  4. Aprire la directory todo e installare le dipendenze.

    cd todo
    npm install
    
  5. Eseguire la nuova applicazione.

    npm start
    
  6. Per visualizzare la nuova applicazione in un browser, passare a http://localhost:3000.

    Screenshot of the Hello World application in a browser window.

    Per arrestare l'applicazione, usare CTRL+C nella finestra del terminale e selezionare y per terminare il processo batch.

Installare i moduli necessari

Il file package.json è uno di quelli creati nella radice del progetto. Questo file contiene un elenco di altri moduli necessari per l'applicazione Node.js. Quando si distribuisce questa applicazione in Azure, questo file viene usato per determinare quali moduli devono essere installati in Azure per supportare l'applicazione. Per questa esercitazione, installare altri due pacchetti.

  1. Installare il modulo @azure/cosmos tramite npm.

    npm install @azure/cosmos
    

Connettere l'applicazione Node.js ad Azure Cosmos DB

Dopo aver completato l'installazione e la configurazione iniziali, si imparerà come scrivere il codice richiesto dall'applicazione todo per comunicare con Azure Cosmos DB.

Creare il modello

  1. Nella radice della directory del progetto creare una nuova directory denominata models.

  2. Nella directory models (modelli) creare un nuovo file denominato taskDao.js. Questo file contiene il codice necessario per creare il contenitore e il database. Definisce inoltre i metodi per leggere, aggiornare, creare e trovare le attività in Azure Cosmos DB.

  3. Copiare il codice seguente nel file 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
    
  4. Salvare e chiudere il file taskDao.js .

Creare il controller

  1. Nella directory routes (route) del progetto creare un nuovo file denominato tasklist.js.

  2. Aggiungere il seguente codice al file tasklist.js. Questo codice carica i moduli CosmosClient e async, usati da tasklist.js. Definisce inoltre la classe TaskList, che viene passata come istanza dell'oggetto TaskDao definito in precedenza:

     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;
    
  3. Salvare e chiudere il file tasklist.js .

Aggiungere config.json

  1. Nella radice della directory del progetto creare un nuovo file denominato config.js.

  2. Aggiungere il codice seguente al file config.js. Questo codice definisce le impostazioni e i valori di configurazione necessari per l'applicazione.

    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;
    
  3. Nel file config.js, aggiornare i valori HOST e AUTH_KEY usando i valori presenti nella pagina Chiavi dell'account Azure Cosmos DB nel portale di Azure.

  4. Salvare e chiudere il file config.js .

Modificare il file app.js

  1. Nella directory del progetto aprire il file app.js . Questo file è stato creato in precedenza quando è stata creata l'applicazione Web Express.

  2. Aggiungere il codice seguente al file app.js. Questo codice definisce il file di configurazione da usare e carica i valori in alcune variabili che si utilizzeranno nelle prossime sezioni.

     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
    
  3. Infine, salvare e chiudere il file app.js.

Creare un'interfaccia utente

Ora, creare l'interfaccia utente per consentire agli utenti di interagire con l'applicazione. L'applicazione Express creata nelle sezioni precedenti usa Jade come motore di visualizzazione.

  1. Il file layout.jade della directory views viene usato come modello globale per altri file .jade. In questo passaggio, verrà modificato in modo da usare Twitter Bootstrap, un toolkit di progettazione di siti Web.

  2. Aprire il file layout.jade nella cartella views e sostituire il contenuto con il codice seguente:

    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')
    

    Il codice comunica al motore Jade di eseguire il rendering di una parte del codice HTML per l'applicazione e crea un blocco denominato content tramite cui è possibile fornire il layout per le pagine di contenuto. Salvare e chiudere il file layout.jade.

  3. Aprire il file index.jade, la vista usata dall'applicazione. Sostituire il contenuto del file con il codice seguente:

    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
    

Il codice estende il layout e fornisce contenuto per il segnaposto content visto nel file layout.jade. In tale layout, sono stati creati due moduli HTML.

Il primo modulo contiene una tabella per i dati e un pulsante che permette di aggiornare gli elementi mediante la pubblicazione nel metodo /completetask del controller.

Il secondo modulo contiene due campi di input e un pulsante che consente di creare un nuovo elemento pubblicando il metodo /addtask del controller, il che è tutto ciò di cui si ha bisogno perché l'applicazione funzioni.

Esecuzione dell'applicazione in locale

Dopo aver creato l'applicazione, è possibile eseguirla localmente usando i passaggi seguenti:

  1. Per testare l'applicazione nel computer locale, eseguire npm start nel terminale per avviare l'applicazione e quindi aggiornare la pagina http://localhost:3000. La pagina dovrebbe ora avere un aspetto simile a quello dello screenshot seguente:

    Screenshot of the My Todo List application in a browser.

    Suggerimento

    Se viene visualizzato un errore relativo al rientro nel file layout.jade o nel file index.jade, assicurarsi che le prime due righe in entrambi i file siano giustificate a sinistra, senza spazi. Se sono presenti spazi davanti alle prime due righe, rimuoverli, salvare entrambi i file e quindi aggiornare la finestra del browser.

  2. Usare i campi Nome elemento e Categoria elemento per immettere una nuova attività, quindi selezionare Aggiungi elemento per creare un documento in Azure Cosmos DB con tali proprietà.

  3. La pagina verrà aggiornata e verrà visualizzato l’elemento appena creato nell'elenco ToDo.

    Screenshot of the application with a new item in the ToDo list.

  4. Per completare un'attività, selezionare la casella di controllo nella colonna Completa, quindi selezionare Aggiorna attività per aggiornare il documento già creato e rimuoverlo dalla visualizzazione.

  5. Per arrestare l'applicazione, premere CTRL+C nella finestra del terminale e quindi selezionare Y per interrompere il processo batch.

Distribuzione dell'applicazione a Servizio app

Dopo che l'applicazione ha avuto esito positivo in locale, è possibile distribuirla su Servizio app di Azure. Nel terminale, assicurarsi di essere nella directory dell'app todo. Distribuire il codice nella cartella locale (todo) usando il comando az webapp up seguente:

az webapp up --sku F1 --name <app-name>

Sostituire <app_name> con un nome univoco nell'ambito di Azure (i caratteri validi sono a-z, 0-9 e -). Un criterio valido consiste nell'usare una combinazione del nome della società e di un identificatore dell'app. Per ulteriori informazioni sulla distribuzione dell'app, vedere Distribuzione dell'app Node.js in Azure.

Il completamento del comando può richiedere alcuni minuti. Il comando fornisce messaggi sulla creazione del gruppo di risorse, sul piano di Servizio app e la risorsa dell'app, la configurazione della registrazione e la distribuzione dello ZIP. Il comando fornisce questi messaggi durante l'esecuzione. Quindi, fornisce un URL per avviare l'app all'indirizzo http://<app-name>.azurewebsites.net, ovvero l'URL dell'app su Azure.

Pulire le risorse

Quando tali risorse non sono più necessarie, è possibile eliminare il gruppo di risorse, l'account Azure Cosmos DB e tutte le risorse correlate. A tale scopo, selezionare il gruppo di risorse usato per l'account Azure Cosmos DB, selezionare Elimina, quindi confermare il nome del gruppo di risorse da eliminare.

Passaggi successivi

È possibile usare le informazioni del cluster di database esistente per la pianificazione della capacità.