Självstudie: Skapa en Node.js webbapp med hjälp av JavaScript SDK för att hantera ett API för NoSQL-konto i Azure Cosmos DB

GÄLLER FÖR: NoSQL

Som utvecklare kan du ha program som använder NoSQL-dokumentdata. Du kan använda ett API för NoSQL-konto i Azure Cosmos DB för att lagra och komma åt dessa dokumentdata. Den här Node.js självstudien visar hur du lagrar och kommer åt data från ett API för NoSQL-konto i Azure Cosmos DB. I självstudien används ett Node.js Express-program som finns på Web Apps-funktionen i Microsoft Azure App Service. I den här självstudien skapar du ett webbaserat program (Att göra-app) som gör att du kan skapa, hämta och slutföra uppgifter. Uppgifterna lagras som JSON-dokument i Azure Cosmos DB.

Den här självstudien visar hur du skapar ett API för NoSQL-konto i Azure Cosmos DB med hjälp av Azure Portal. Utan ett kreditkort eller en Azure-prenumeration kan du:

  • Konfigurera ett kostnadsfritt Prova Azure Cosmos DB-konto.
  • Skapa och kör en webbapp som bygger på Node.js SDK för att skapa en databas och container.
  • Lägga till objekt i containern.

Den här självstudien använder JavaScript SDK version 3.0 och omfattar följande uppgifter:

  • Skapa ett Azure Cosmos DB-konto
  • Skapa ett nytt Node.js-program
  • Ansluta programmet till Azure Cosmos DB
  • Köra och distribuera programmet till Azure

Förutsättningar

Innan du följer anvisningarna i den här artikeln bör du se till att du har följande resurser:

Skapa ett Azure Cosmos DB-konto

Börja med att skapa ett Azure Cosmos DB-konto. Om du redan har ett konto eller om du använder Azure Cosmos DB-emulatorn för den här självstudien kan du gå vidare till Skapa ett nytt Node.js program.

  1. Välj Skapa en resurs på Azure Portal-menyn eller på sidan Start.

  2. Sök efter Azure Cosmos DB. Välj Skapa>Azure Cosmos DB.

  3. På sidan Skapa ett Azure Cosmos DB-konto väljer du alternativet Skapa i avsnittet Azure Cosmos DB for NoSQL .

    Azure Cosmos DB innehåller flera API:er:

    • NoSQL för dokumentdata
    • PostgreSQL
    • MongoDB, för dokumentdata
    • Apache Cassandra
    • Tabell
    • Apache Gremlin, för grafdata

    Mer information om API:et för NoSQL finns i Välkommen till Azure Cosmos DB.

  4. På sidan Skapa Azure Cosmos DB-konto anger du de grundläggande inställningarna för det nya Azure Cosmos DB-kontot.

    Inställning Värde Beskrivning
    Prenumeration Prenumerationens namn Välj den Azure-prenumeration som ska användas för det här Azure Cosmos DB-kontot.
    Resursgrupp Namn på resursgrupp Välj en resursgrupp eller välj Skapa ny och ange sedan ett unikt namn för den nya resursgruppen.
    Account Name Ett unikt namn Ange ett namn för att identifiera ditt Azure Cosmos DB-konto. Eftersomdocuments.azure.com läggs till det namn du anger för att skapa din URI måste du använda ett unikt namn. Namnet får bara innehålla gemener, siffror och bindestreck (-). Det måste vara 3–44 tecken.
    Location Den region som är närmast dina användare Välj en geografisk plats som värd för ditt Azure Cosmos DB-konto. Använd den plats som är närmast dina användare för att ge dem så snabb åtkomst till data som möjligt.
    Kapacitetsläge Etablerat dataflöde eller serverlöst Välj Etablerat dataflöde för att skapa ett konto i etablerat dataflödesläge . Välj Serverlös för att skapa ett konto i serverlöst läge.
    Tillämpa rabatt på den kostnadsfria nivån för Azure Cosmos DB Använd eller Använd inte Med den kostnadsfria Azure Cosmos DB-nivån får du de första 1 000 RU/s och 25 GB lagringsutrymme kostnadsfritt på ett konto. Läs mer om den kostnadsfria nivån.
    Begränsa det totala kontodataflödet Markerad eller inte Begränsa den totala mängden dataflöde som kan etableras för det här kontot. Den här gränsen förhindrar oväntade avgifter relaterade till etablerat dataflöde. Du kan uppdatera eller ta bort den här gränsen när ditt konto har skapats.

    Du kan ha upp till ett Azure Cosmos DB-konto på kostnadsfri nivå per Azure-prenumeration och måste välja när du skapar kontot. Om du inte ser alternativet att tillämpa rabatten på den kostnadsfria nivån har ett annat konto i prenumerationen redan aktiverats med den kostnadsfria nivån.

    Skärmbild som visar sidan Skapa Azure Cosmos DB-konto.

    Anteckning

    Följande alternativ är inte tillgängliga om du väljer Serverlös som Kapacitetsläge:

    • Tillämpa rabatt för kostnadsfri nivå
    • Begränsa det totala kontodataflödet
  5. Konfigurera följande information på fliken Global distribution . Du kan lämna standardvärdena för den här snabbstarten:

    Inställningen Värde Beskrivning
    Geo-redundans Inaktivera Aktivera eller inaktivera global distribution på ditt konto genom att koppla ihop din region med en parregion. Du kan lägga till fler regioner i ditt konto senare.
    Skrivåtgärder för flera regioner Inaktivera Med skrivfunktioner i flera regioner kan du dra nytta av det etablerade dataflödet för dina databaser och containrar över hela världen.
    Tillgänglighetszoner Inaktivera Tillgänglighetszoner hjälper dig att ytterligare förbättra programmets tillgänglighet och återhämtning.

    Anteckning

    Följande alternativ är inte tillgängliga om du väljer Serverlös som Kapacitetsläge på föregående grundläggande sida:

    • Geo-redundans
    • Skrivåtgärder för flera regioner
  6. Du kan också konfigurera mer information på följande flikar:

    • Nätverk. Konfigurera åtkomst från ett virtuellt nätverk.
    • Säkerhetskopieringspolicy. Konfigurera antingen regelbunden eller kontinuerlig säkerhetskopieringspolicy.
    • Kryptering. Använd antingen tjänsthanterad nyckel eller en kundhanterad nyckel.
    • Taggar. Taggar är namn/värde-par som gör att du kan kategorisera resurser och visa konsoliderad fakturering genom att tillämpa samma tagg på flera resurser och resursgrupper.
  7. Välj Granska + skapa.

  8. Granska kontoinställningarna och välj sedan Skapa. Det tar några minuter att skapa kontot. Vänta tills portalsidan visar meddelandet Distributionen är klar.

    Skärmbild som visar att distributionen är klar.

  9. Välj Gå till resurs för att gå till sidan för Azure Cosmos DB-kontot.

    Skärmbild som visar azure Cosmos DB-kontosidan.

Gå till azure Cosmos DB-kontosidan och välj Nycklar. Kopiera värdena som ska användas i det webbprogram som du skapar härnäst.

Skärmbild av Azure Portal med knappen Nycklar markerad på Azure Cosmos DB-kontosidan

Skapa ett nytt Node.js-program

Lär dig nu hur du skapar ett grundläggande Hello World Node.js projekt med hjälp av Express-ramverket.

  1. Öppna din favoritterminal, till exempel Node.js-kommandotolken.

  2. Navigera till den katalog där du vill lagra det nya programmet.

  3. Skapa ett nytt program kallat todo med hjälp av Express Generator.

    express todo
    
  4. Öppna todo-katalogen och installera beroenden.

    cd todo
    npm install
    
  5. Kör det nya programmet.

    npm start
    
  6. Om du vill visa ditt nya program i en webbläsare går du till http://localhost:3000.

    Skärmbild av Hello World-programmet i ett webbläsarfönster.

    Stoppa programmet genom att använda CTRL +C i terminalfönstret och välj y för att avsluta batchjobbet.

Installera de moduler som krävs

Filen package.json är en av filerna som skapas i projektets rot. Den här filen innehåller en lista över andra moduler som krävs för ditt Node.js program. När du distribuerar det här programmet till Azure används den här filen för att avgöra vilka moduler som ska installeras på Azure för att stödja ditt program. Installera ytterligare två paket för den här självstudien.

  1. Installera modulen @azure/cosmos via npm.

    npm install @azure/cosmos
    

Ansluta Node.js-programmet till Azure Cosmos DB

När du har slutfört den första installationen och konfigurationen lär du dig att skriva den kod som krävs för att kunna kommunicera med Azure Cosmos DB.

Skapa modellen

  1. Skapa en ny katalog med namnet models i projektkatalogens rot.

  2. I katalogen models skapar du en ny fil med namnet taskDao.js. Den här filen innehåller den kod som krävs för att skapa databasen och containern. Den definierar även metoder för att läsa, uppdatera, skapa och hitta aktiviteter i Azure Cosmos DB.

  3. Kopiera följande kod till filentaskDao.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. Spara och stäng filen taskDao.js.

Skapa styrningen

  1. I projektets routes-katalog skapar du en ny fil med namnet tasklist.js.

  2. Lägg till följande kod i tasklist.js. Den här koden läser in modulerna CosmosClient och async, som används av tasklist.js. Koden definierar även klassen TaskList, som skickas som en instans av det TaskDao-objekt som vi definierade tidigare:

     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. Spara och stäng filen tasklist.js.

Lägg till config.js

  1. Vid roten av projektkatalogen skapar du en ny fil med namnet config.js.

  2. Lägg till följande kod i filen config.js. Den här koden definierar konfigurationsinställningar och värden som behövs i appen.

    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. I filenconfig.js uppdaterar du värdena för HOST och AUTH_KEY med hjälp av värdena på sidan Nycklar för ditt Azure Cosmos DB-konto på Azure Portal.

  4. Spara och stäng filen config.js.

Ändra app.js

  1. Öppna filen app.js i projektkatalogen. Den här filen skapades tidigare när Express-webbappen skapades.

  2. Lägg till följande kod i filen app.js. Den här koden definierar konfigurationsfilen som ska användas och läser in värdena i några variabler som du ska använda i nästa avsnitt.

     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. Avsluta med att spara och stänga filen app.js.

Skapa ett användargränssnitt

Skapa nu användargränssnittet så att en användare kan interagera med programmet. Express-programmet som du skapade i föregående avsnitt använder Jade som visningsmotor.

  1. Filen layout.jade i katalogen views används som en global mall för andra .jade-filer. I det här steget ändrar du den så att den använder Twitter Bootstrap, som är en verktygslåda som används för att utforma en webbplats.

  2. Öppna filen layout.jade i mappen views och ersätt innehållet med följande kod:

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

    Den här koden instruerar Jade-motorn att rendera html för programmet och skapar ett block med namnet innehåll där du kan ange layouten för innehållssidorna. Spara och stäng filen layout.jade.

  3. Öppna filen index.jade , den vy som används av programmet. Ersätt innehållet i filen med följande kod:

    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
    

Den här koden utökar layouten och tillhandahåller innehåll för den platshållare för innehåll som du såg i filen layout.jade . I den layouten skapade du två HTML-formulär.

Det första formuläret innehåller en tabell för dina data och en knapp som gör att du kan uppdatera objekt genom att publicera till / completeTask-metoden för kontrollanten.

Det andra formuläret innehåller två indatafält och en knapp som gör att du kan skapa ett nytt objekt genom att publicera till / addtask-metoden för kontrollanten, vilket är allt du behöver för att programmet ska fungera.

Köra ditt program lokalt

När du har skapat programmet kan du köra det lokalt med hjälp av följande steg:

  1. Om du vill testa programmet på den lokala datorn kör npm start du i terminalen för att starta programmet och uppdaterar http://localhost:3000 sedan sidan. Sidan bör nu se ut som på följande skärmbild:

    Skärmbild av programmet Min att göra-lista i en webbläsare.

    Tips

    Om du får ett felmeddelande om indraget i filen layout.jade eller filen index.jade kontrollerar du att de två första raderna i båda filerna är vänsterjusterade, utan blanksteg. Om det finns blanksteg före de två första raderna tar du bort dem. Spara filerna och uppdatera sedan webbläsarfönstret.

  2. Använd fälten Objektnamn och Objektkategori för att ange en ny aktivitet och välj sedan Lägg till objekt för att skapa ett dokument i Azure Cosmos DB med dessa egenskaper.

  3. Sidan uppdateras så att det nyligen skapade objektet visas i att göra-listan.

    Skärmbild av programmet med ett nytt objekt i att göra-listan.

  4. Om du vill slutföra en uppgift markerar du kryssrutan i kolumnen Slutför och väljer sedan Uppdatera aktiviteter för att uppdatera dokumentet som du redan har skapat och ta bort det från vyn.

  5. Om du vill stoppa programmet trycker du på CTRL+C i terminalfönstret och väljer sedan y för att avsluta batchjobbet.

Distribuera ditt program till App Service

När programmet har lyckats lokalt kan du distribuera det till Azure App Service. Kontrollera att du är i att göra-appkatalogen i terminalen. Distribuera koden i din lokala mapp (todo) med hjälp av följande az webapp up-kommando :

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

Ersätt <app_name> med ett namn som är unikt för alla Azure (giltiga tecken är a-z, 0-9 och -). Ett bra mönster är att använda en kombination av företagets namn och en appidentifierare. Mer information om appdistributionen finns i Node.js appdistribution i Azure.

Det kan ta några minuter att slutföra kommandot. Kommandot innehåller meddelanden om hur du skapar resursgruppen, App Service-planen och appresursen, konfigurerar loggning och utför ZIP-distribution. Kommandot tillhandahåller dessa meddelanden när du kör. Sedan får du en URL för att starta appen på http://<app-name>.azurewebsites.net, vilket är appens URL i Azure.

Rensa resurser

När dessa resurser inte längre behövs kan du ta bort resursgruppen, Azure Cosmos DB-kontot och alla relaterade resurser. Om du vill göra detta markerar du den resursgrupp som du använde för Azure Cosmos DB-kontot. Välj sedan Ta bort och bekräfta namnet på den resursgrupp som du vill ta bort.

Nästa steg

Du kan använda information om ditt befintliga databaskluster för kapacitetsplanering.