Руководство. Создание веб-приложения Node.js с помощью пакета SDK JavaScript для управления учетной записью API для NoSQL в Azure Cosmos DB

ОБЛАСТЬ ПРИМЕНЕНИЯ: NoSQL

Как у разработчика у вас могут быть приложения, использующие данные документов NoSQL. Вы можете использовать учетную запись API для NoSQL в Azure Cosmos DB для хранения и доступа к этим данным документа. В этом Node.js руководстве показано, как хранить и получать доступ к данным из учетной записи API для NoSQL в Azure Cosmos DB. В этом руководстве используется приложение Node.js Express, размещенное в компоненте веб-приложения службы Microsoft приложение Azure. В этом руководстве вы создадите веб-приложение (приложение Todo), которое позволяет создавать, извлекать и выполнять задачи. Задачи будут храниться в виде документов JSON в Azure Cosmos DB.

В этом руководстве показано, как создать учетную запись API для NoSQL в Azure Cosmos DB с помощью портал Azure. Без кредитной карты или подписки Azure вы можете:

  • Настройте бесплатную учетную запись Azure Cosmos DB.
  • Создайте и запустите веб-приложение, созданное на основе пакета SDK Node.js для создания базы данных и контейнера.
  • добавлять элементы в контейнер;

В этом руководстве используется пакет SDK javaScript версии 3.0 и рассматриваются следующие задачи:

  • Создание учетной записи Azure Cosmos DB
  • Создание нового приложения Node.js
  • подключение приложения к Azure Cosmos DB;
  • запуск и развертывание приложения в Azure.

Необходимые компоненты

Перед выполнением инструкций, приведенных в этой статье, обеспечьте наличие следующих ресурсов:

Создание учетной записи Azure Cosmos DB

Начните с создания учетной записи Azure Cosmos DB. Если у вас уже есть учетная запись или вы используете эмулятор Azure Cosmos DB для этого руководства, можно перейти к созданию нового приложения Node.js.

  1. На домашней странице или в меню портала Azure выберите Создать ресурс.

  2. Найдите Azure Cosmos DB. Выберите "Создать>Azure Cosmos DB".

  3. На странице "Создание учетной записи Azure Cosmos DB" выберите параметр "Создать" в разделе Azure Cosmos DB для NoSQL.

    Azure Cosmos DB предоставляет несколько API:

    • NoSQL для данных документа
    • PostgreSQL
    • MongoDB для данных документа
    • Apache Cassandra
    • Таблица
    • Apache Gremlin для данных графа

    Дополнительные сведения об API для NoSQL см. в статье "Добро пожаловать в Azure Cosmos DB".

  4. На странице "Создание учетной записи Azure Cosmos DB" введите основные параметры для новой учетной записи Azure Cosmos DB.

    Параметр значение Описание
    Подписка Название подписки Выберите подписку Azure, которую вы хотите использовать для этой учетной записи Azure Cosmos DB.
    Группа ресурсов Имя группы ресурсов Выберите группу ресурсов или Создать, затем введите уникальное имя для новой группы ресурсов.
    Имя учетной записи Уникальное имя Введите имя для идентификации учетной записи Azure Cosmos DB. Так как элемент documents.azure.com добавляется к указанному вами имени для создания URI, используйте уникальное имя. Имя может содержать только строчные буквы, цифры и символ дефиса (-). Он должен иметь 3–44 символа.
    Расположение Ближайший к пользователям регион Выберите географическое расположение для размещения учетной записи Azure Cosmos DB. Используйте ближайшее к пользователям расположение, чтобы предоставить им максимально быстрый доступ к данным.
    Режим емкости Подготовленная пропускная способность или Бессерверный режим Выберите Подготовленная пропускная способность, чтобы создать учетную запись в режиме подготовленной пропускной способности. Выберите Бессерверный, чтобы создать учетную запись в режиме Бессерверный.
    Применение скидки на основе категории "Бесплатный" для Azure Cosmos DB Применить или не применять В категории "Бесплатный" Azure Cosmos DB для учетной записи бесплатно предоставляются первые 1000 единиц запросов в секунду и 25 ГБ свободного места в хранилище. Ознакомьтесь с дополнительными сведениями о категории "Бесплатный".
    Ограничить общую пропускную способность учетной записи Выбранный или нет Ограничить общий объем пропускной способности, которую можно подготовить для этой учетной записи. Это ограничение предотвращает непредвиденные расходы, связанные с подготовленной пропускной способностью. Вы можете обновить или удалить это ограничение после создания учетной записи.

    Вы можете иметь до одного уровня бесплатной учетной записи Azure Cosmos DB на подписку Azure и принять участие при создании учетной записи. Если вы не видите варианта подачи заявки на скидку на основе категории "Бесплатный", это означает, что в подписке уже включена другая учетная запись категории "Бесплатный".

    Снимок экрана: страница

    Примечание.

    Следующие параметры недоступны, если вы выбрали значение Бессерверный для параметра Режим емкости:

    • Применить скидку бесплатного уровня
    • Ограничить общую пропускную способность учетной записи
  5. На вкладке Глобальное распределение настройте следующие сведения. При работе с этим кратким руководством можно оставить значения по умолчанию:

    Параметр значение Описание
    Геоизбыточность Отключить Включает или отключает глобальное распределение в вашей учетной записи, связывая ваш регион с парным регионом. В дальнейшем в учетную запись можно добавить дополнительные регионы.
    Операции записи с поддержкой нескольких регионов Отключить Поддержка записи в несколько регионов позволяет использовать подготовленную пропускную способность для баз данных и контейнеров по всему миру.
    зоны доступности; Отключить Зоны доступности помогают повысить доступность и устойчивость приложения.

    Примечание.

    Следующие параметры недоступны при выборе бессерверного режима в качестве режима емкости на предыдущей странице "Основные сведения".

    • Геоизбыточность
    • Операции записи с поддержкой нескольких регионов
  6. При необходимости можно настроить дополнительные сведения на следующих вкладках:

  7. Выберите Review + create (Просмотреть и создать).

  8. Проверьте параметры учетной записи, а затем нажмите кнопку Создать. Создание учетной записи занимает несколько минут. Дождитесь, пока на странице портала появится сообщение Развертывание выполнено.

    Снимок экрана: развертывание завершено.

  9. Выберите Перейти к ресурсу, чтобы перейти на страницу учетной записи Azure Cosmos DB.

    Снимок экрана: страница учетной записи Azure Cosmos DB.

Перейдите на страницу учетной записи Azure Cosmos DB и нажмите на кнопку Ключи. Скопируйте значения, которые понадобятся в создаваемом веб-приложении.

Снимок экрана: портал Azure с выделенной кнопкой

Создание нового приложения Node.js

Теперь узнайте, как создать базовый проект Hello World Node.js с помощью платформы Express.

  1. Откройте предпочитаемый терминал, например командную строку Node.js.

  2. Перейдите в каталог, в котором будет сохранено новое приложение.

  3. С помощью генератора Express создайте новое приложение с именем todo.

    express todo
    
  4. Откройте каталог todo и установите зависимости.

    cd todo
    npm install
    
  5. Запустите новое приложение.

    npm start
    
  6. Чтобы просмотреть новое приложение в браузере, перейдите в раздел http://localhost:3000.

    Снимок экрана: приложение Hello World в окне браузера.

    Остановите приложение, нажав клавиши CTRL+C в окне терминала, и выберите Y, чтобы завершить пакетное задание.

Установка необходимых модулей

Файл package.json является одним из файлов, создаваемых в корневой папке проекта. Этот файл содержит список дополнительных модулей, требуемых для приложения Node.js. При развертывании этого приложения в Azure этот файл будет использоваться для определения модулей, которые следует установить в Azure для поддержки вашего приложения. Для работы с этим руководством установите еще два пакета.

  1. Установите модуль @azure/cosmos через npm.

    npm install @azure/cosmos
    

Подключение приложения Node.js к Azure Cosmos DB

После завершения начальной настройки и настройки узнайте, как написать код, который требуется приложению todo для взаимодействия с Azure Cosmos DB.

Создание модели

  1. В корне каталога проекта создайте каталог с именем models.

  2. В каталоге models создайте новый файл с именем taskDao.js. Этот файл содержит код, необходимый для создания базы данных и контейнера. Он также определяет методы для чтения, обновления, создания и поиска задач в Azure Cosmos DB.

  3. Скопируйте следующий код в файл 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. Сохраните и закройте файл taskDao.js .

Создание контроллера

  1. В каталоге проекта routes создайте новый файл с именем tasklist.js.

  2. Добавьте в tasklist.jsследующий код. Этот код загружает модули CosmosClient и async, используемые файлом tasklist.js. Он также определяет класс 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;
    
  3. Сохраните и закройте файл tasklist.js .

Добавление config.js

  1. В корне каталога проекта создайте файл с именем config.js.

  2. Добавьте следующий код в файл 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;
    
  3. В файле config.js обновите значения HOST и AUTH_KEY с помощью значений, найденных на странице "Ключи" учетной записи Azure Cosmos DB в портал Azure.

  4. Сохраните и закройте файл config.js .

Изменение app.js

  1. В каталоге проекта откройте файл app.js . Этот файл был создан ранее, при создании веб-приложения Express.

  2. Добавьте следующий код в файл 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
    
  3. Наконец, сохраните и закройте файл app.js.

Сборка пользовательского интерфейса

Теперь создайте пользовательский интерфейс, чтобы пользователь смог взаимодействовать с приложением. Приложение Express, созданное в предыдущих разделах, использует Jade в качестве обработчика представлений.

  1. Файл layout.jade в каталоге views используется как глобальный шаблон для других файлов .jade. На этом шаге вы измените его, чтобы использовать Bootstrap, который является набором средств, используемым для разработки веб-сайта.

  2. Откройте файл layout.jade, расположенный в папке views, и замените его содержимое следующим кодом:

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

    Этот код сообщает обработчику Jade отрисовку некоторых HTML для приложения и создает блок с именем содержимого , где можно указать макет для страниц содержимого. Сохраните и закройте файл layout.jade.

  3. Откройте файл index.jade, представление, используемое приложением. Замените содержимое файла следующим кодом:

    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
    

Этот код расширяет макет и предоставляет содержимое для заполнителя контента , который вы видите в файле layout.jade . В этом макете вы создали две формы HTML.

Первая форма содержит таблицу для данных и кнопку, которая позволяет обновлять элементы, публикуя метод /completeTask контроллера.

Вторая форма содержит два поля ввода и кнопку, которая позволяет создавать новый элемент, публикуя метод /addtask контроллера, который необходим для работы приложения.

Локальный запуск приложения

После создания приложения его можно запустить локально, выполнив следующие действия:

  1. Чтобы протестировать приложение на локальном компьютере, запустите npm start в терминале, чтобы запустить приложение, а затем обновите страницу http://localhost:3000 . Теперь страница должна выглядеть следующим образом:

    Снимок экрана: приложение

    Совет

    Если вы получаете сообщение об ошибке отступа в файле layout.jade или файле index.jade, убедитесь, что первые две строки в обоих файлах оправданы без пробелов. Если перед первыми двумя строками есть пробелы, удалите их, сохраните оба файла и затем обновите окно браузера.

  2. Используйте поля "Имя элемента" и "Категория элемента", чтобы ввести новую задачу, а затем выберите " Добавить элемент ", чтобы создать документ в Azure Cosmos DB с этими свойствами.

  3. Страница обновляется для отображения только что созданного элемента в списке ToDo.

    Снимок экрана: приложение с новым элементом в списке ToDo.

  4. Чтобы завершить задачу, установите флажок в столбце "Завершить", а затем выберите "Обновить задачи ", чтобы обновить уже созданный документ и удалить его из представления.

  5. Чтобы остановить приложение, нажмите клавиши CTRL+C в окне терминала, а затем выберите y , чтобы завершить пакетное задание.

Развертывание приложения в Службе приложений

Если ваше приложение успешно работает локально, его можно развернуть в Службе приложений Azure. В терминале убедитесь, что вы находитесь в каталоге приложения todo. Разверните код в локальной папке (todo) с помощью следующей команды az webapp up :

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

Замените <app_name> уникальным в пределах Azure именем (допустимые символы: a–z, 0–9, и -). Рекомендуется использовать сочетание названия компании и идентификатора приложения. Дополнительные сведения о развертывании приложений см. в статье Node.js развертывании приложений в Azure.

Выполнение команды может занять несколько минут. Эта команда предоставляет сообщения о создании группы ресурсов, плане Служба приложений и ресурсе приложения, настройке ведения журнала и развертывании ZIP. Эта команда предоставляет эти сообщения во время выполнения. Затем будет предоставлен URL-адрес для запуска приложения: http://<app-name>.azurewebsites.net (URL-адрес приложения в Azure).

Очистка ресурсов

Если эти ресурсы больше не нужны, можно удалить группу ресурсов, учетную запись Azure Cosmos DB и все связанные ресурсы. Для этого выберите группу ресурсов, которая использовалась для учетной записи Azure Cosmos DB, выберите Удалить, а затем подтвердите имя удаляемой группы ресурсов.

Следующие шаги

Для планирования ресурсов можно использовать сведения об имеющемся кластере базы данных.