Учебники

DocumentDB — Краткое руководство

DocumentDB — Введение

В этой главе мы кратко обсудим основные концепции NoSQL и базы данных документов. У нас также будет краткий обзор DocumentDB.

NoSQL Document Database

DocumentDB — это новейшая база данных Microsoft NoSQL, поэтому, когда вы говорите «база данных документов NoSQL», что именно мы подразумеваем под «NoSQL» и «база данных документов»?

  • SQL означает язык структурированных запросов, который является традиционным языком запросов для реляционных баз данных. SQL часто приравнивают к реляционным базам данных.

  • Действительно более полезно думать о базе данных NoSQL как о нереляционной базе данных, поэтому NoSQL действительно означает нереляционную.

SQL означает язык структурированных запросов, который является традиционным языком запросов для реляционных баз данных. SQL часто приравнивают к реляционным базам данных.

Действительно более полезно думать о базе данных NoSQL как о нереляционной базе данных, поэтому NoSQL действительно означает нереляционную.

Существуют различные типы баз данных NoSQL, которые включают хранилища значений ключей, такие как —

  • Azure Table Storage.
  • Основанные на колонках магазины как Кассандра.
  • Граф базы данных, такие как NEO4.
  • Базы данных документов, такие как MongoDB и Azure DocumentDB.

Azure DocumentDB

Microsoft официально запустила Azure DocumentDB 8 апреля 2015 года, и ее, безусловно, можно охарактеризовать как типичную базу данных документов NoSQL. Он масштабируем и работает с JSON-документами без схемы.

  • DocumentDB — это действительно бесплатная база данных NoSQL для базы данных документов, разработанная для современных мобильных и веб-приложений.

  • Он также обеспечивает стабильно быстрое чтение и запись, гибкость схемы и возможность легко масштабировать базу данных вверх и вниз по требованию.

  • Он не предполагает и не требует никакой схемы для документов JSON, которые он индексирует.

  • DocumentDB автоматически индексирует каждое свойство в документе, как только документ добавляется в базу данных.

  • DocumentDB позволяет выполнять сложные специальные запросы с использованием языка SQL, и каждый документ мгновенно запрашивается в момент его создания, и вы можете выполнять поиск по любому свойству в любом месте иерархии документов.

DocumentDB — это действительно бесплатная база данных NoSQL для базы данных документов, разработанная для современных мобильных и веб-приложений.

Он также обеспечивает стабильно быстрое чтение и запись, гибкость схемы и возможность легко масштабировать базу данных вверх и вниз по требованию.

Он не предполагает и не требует никакой схемы для документов JSON, которые он индексирует.

DocumentDB автоматически индексирует каждое свойство в документе, как только документ добавляется в базу данных.

DocumentDB позволяет выполнять сложные специальные запросы с использованием языка SQL, и каждый документ мгновенно запрашивается в момент его создания, и вы можете выполнять поиск по любому свойству в любом месте иерархии документов.

DocumentDB — Ценообразование

DocumentDB оплачивается на основе количества коллекций, содержащихся в учетной записи базы данных. Каждая учетная запись может иметь одну или несколько баз данных, а каждая база данных может иметь практически неограниченное количество коллекций, хотя первоначальная квота по умолчанию составляет 100. Эту квоту можно отменить, обратившись в службу поддержки Azure.

  • Коллекция — это не только единица измерения, но и единица стоимости, поэтому в DocumentDB вы платите за каждую коллекцию, которая имеет емкость до 10 ГБ.

  • Как минимум, вам понадобится одна коллекция S1 для хранения документов в базе данных, которая будет стоить примерно 25 долларов в месяц, которая оплачивается по вашей подписке Azure.

  • Поскольку ваша база данных увеличивается в размерах и превышает 10 ГБ, вам необходимо приобрести другую коллекцию для хранения дополнительных данных.

  • Каждая коллекция S1 будет давать вам 250 единиц запросов в секунду, а если этого недостаточно, вы можете масштабировать коллекцию до уровня S2 и получать 1000 единиц запросов в секунду примерно за 50 долларов в месяц.

  • Вы также можете включить S3 и платить около 100 долларов в месяц.

Коллекция — это не только единица измерения, но и единица стоимости, поэтому в DocumentDB вы платите за каждую коллекцию, которая имеет емкость до 10 ГБ.

Как минимум, вам понадобится одна коллекция S1 для хранения документов в базе данных, которая будет стоить примерно 25 долларов в месяц, которая оплачивается по вашей подписке Azure.

Поскольку ваша база данных увеличивается в размерах и превышает 10 ГБ, вам необходимо приобрести другую коллекцию для хранения дополнительных данных.

Каждая коллекция S1 будет давать вам 250 единиц запросов в секунду, а если этого недостаточно, вы можете масштабировать коллекцию до уровня S2 и получать 1000 единиц запросов в секунду примерно за 50 долларов в месяц.

Вы также можете включить S3 и платить около 100 долларов в месяц.

DocumentDB — Преимущества

DocumentDB отличается уникальными возможностями. Azure DocumentDB предлагает следующие ключевые возможности и преимущества.

Схема бесплатно

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

В отличие от базы данных документов не имеет определенной схемы, и каждый документ может быть структурирован по-разному.

Синтаксис SQL

DocumentDB позволяет выполнять сложные специальные запросы с использованием языка SQL, и каждый документ мгновенно запрашивается в момент его создания. Вы можете искать любое свойство в любом месте иерархии документов.

Перестраиваемая последовательность

Он предоставляет некоторые детализированные, четко определенные уровни согласованности, что позволяет вам находить разумные компромиссы между согласованностью, доступностью и задержкой.

Вы можете выбрать один из четырех четко определенных уровней согласованности, чтобы достичь оптимального компромисса между согласованностью и производительностью. Для запросов и операций чтения DocumentDB предлагает четыре различных уровня согласованности:

  • сильный
  • Ограниченность-черствость
  • сессия
  • эвентуальный

Эластичная шкала

Масштабируемость — это название игры с NoSQL, которую обеспечивает DocumentDB. DocumentDB уже доказал свой масштаб.

  • Основные службы, такие как Office OneNote и Xbox, уже поддерживаются DocumentDB с базами данных, содержащими десятки терабайт документов JSON, более миллиона активных пользователей и работающими на постоянной основе с доступностью 99,95%.

  • Вы можете гибко масштабировать DocumentDB с предсказуемой производительностью, создавая больше модулей по мере роста вашего приложения.

Основные службы, такие как Office OneNote и Xbox, уже поддерживаются DocumentDB с базами данных, содержащими десятки терабайт документов JSON, более миллиона активных пользователей и работающими на постоянной основе с доступностью 99,95%.

Вы можете гибко масштабировать DocumentDB с предсказуемой производительностью, создавая больше модулей по мере роста вашего приложения.

Полностью управляемый

DocumentDB доступна как полностью управляемая облачная платформа в качестве службы, работающей в Azure.

  • Вам просто нечего устанавливать или управлять.

  • Здесь нет серверов, кабелей, операционных систем или обновлений, нет реплик для настройки.

  • Microsoft выполняет всю эту работу и поддерживает работу службы.

  • Буквально через несколько минут вы можете начать работать с DocumentDB, используя только браузер и подписку Azure.

Вам просто нечего устанавливать или управлять.

Здесь нет серверов, кабелей, операционных систем или обновлений, нет реплик для настройки.

Microsoft выполняет всю эту работу и поддерживает работу службы.

Буквально через несколько минут вы можете начать работать с DocumentDB, используя только браузер и подписку Azure.

DocumentDB — настройка среды

Microsoft предоставляет бесплатную версию Visual Studio, которая также содержит SQL Server, и ее можно загрузить с https://www.visualstudio.com.

Монтаж

Шаг 1 — После завершения загрузки запустите установщик. Следующий диалог будет отображен.

монтажник

Шаг 2 — Нажмите на кнопку Установить, и он начнет процесс установки.

Процесс установки

Шаг 3 — После успешного завершения процесса установки вы увидите следующее диалоговое окно.

Перезагрузить сейчас

Шаг 4 — Закройте это диалоговое окно и перезагрузите компьютер, если это необходимо.

Шаг 5 — Теперь откройте Visual Studio из меню Пуск, которое откроет диалоговое окно ниже. Впервые это займет некоторое время только для подготовки.

открытая визуальная студия

Как только все будет сделано, вы увидите главное окно Visual Studio.

Главное окно

Шаг 6 — Давайте создадим новый проект из File → New → Project.

Создать новый проект

Шаг 7 — Выберите Консольное приложение, введите DocumentDBDemo в поле «Имя» и нажмите кнопку «ОК».

Шаг 8 — В обозревателе решений щелкните правой кнопкой мыши свой проект.

Щелкните правой кнопкой мыши на проекте

Шаг 9 — Выберите Управление пакетами NuGet, которое откроет следующее окно в Visual Studio и в поле ввода Поиск в Интернете найдите клиентскую библиотеку DocumentDB.

Управление пакетами NuGet

Шаг 10 — Установите последнюю версию, нажав кнопку «Установить».

Принятие лицензии

Шаг 11 — Нажмите «Я принимаю». После завершения установки вы увидите сообщение в окне вывода.

Запустить приложение

Теперь вы готовы запустить приложение.

DocumentDB — Создать аккаунт

Чтобы использовать Microsoft Azure DocumentDB, необходимо создать учетную запись DocumentDB. В этой главе мы создадим учетную запись DocumentDB с помощью портала Azure.

Шаг 1. Войдите на веб-сайт https://portal.azure.com, если у вас уже есть подписка Azure, в противном случае сначала необходимо войти в систему.

Вы увидите основную панель инструментов. Он полностью настраивается, поэтому вы можете расположить эти плитки любым удобным для вас способом, изменить их размер, добавить или удалить плитки для вещей, которые вы часто используете или больше не делаете.

Dashbord

Шаг 2 — Выберите «Новый» вариант в верхней левой части страницы.

Выберите новый вариант

Шаг 3. Теперь выберите «Данные + хранилище»> «Azure DocumentDB», и вы увидите следующий раздел «Новая учетная запись DocumentDB».

Azure DocumentDB

Нам нужно придумать глобально уникальное имя (ID), которое в сочетании с .documents.azure.com является общедоступной конечной точкой нашей учетной записи DocumentDB. Все базы данных, которые мы создаем под этой учетной записью, могут быть доступны через Интернет с помощью этой конечной точки.

Шаг 4 — Давайте назовем его azuredocdbdemo и нажмите на Resource Group → new_resource.

Ресурсная группа

Шаг 5. Выберите местоположение, т. Е. В каком дата-центре Microsoft вы хотите разместить эту учетную запись. Выберите местоположение и выберите свой регион.

Выберите место

Шаг 6 — Установите флажок Закрепить на приборной панели и просто нажмите кнопку Создать.

Кнопка Создать

Вы можете видеть, что плитка уже была добавлена ​​в Dashboard, и это дает нам знать, что учетная запись создается. На самом деле может потребоваться несколько минут для настройки новой учетной записи, в то время как DocumentDB выделяет конечную точку, обеспечивает реплики и выполняет другую работу в фоновом режиме.

Как только это будет сделано, вы увидите панель инструментов.

Панель инструментов аккаунта

Шаг 7 — Теперь нажмите на созданную учетную запись DocumentDB, и вы увидите подробный экран в виде следующего изображения.

Создан Documentdb

DocumentDB — подключить аккаунт

Когда вы начинаете программировать на DocumentDB, самый первый шаг — это подключение. Поэтому для подключения к вашей учетной записи DocumentDB вам понадобятся две вещи;

  • Конечная точка
  • Ключ авторизации

Конечная точка

Конечная точка — это URL-адрес вашей учетной записи DocumentDB, который создается путем объединения имени вашей учетной записи DocumentDB с .documents.azure.com. Давайте перейдем к панели инструментов.

Конечная точка

Теперь нажмите на созданную учетную запись DocumentDB. Вы увидите детали, как показано на следующем изображении.

нажмите на созданную DocumentDB

Когда вы выбираете опцию «Ключи», она отображает дополнительную информацию, как показано на следующем рисунке. Вы также увидите URL своей учетной записи DocumentDB, которую вы можете использовать в качестве конечной точки.

выбор ключей

Ключ авторизации

Ключ авторизации содержит ваши учетные данные и существует два типа ключей. Главный ключ обеспечивает полный доступ ко всем ресурсам в учетной записи, а маркеры ресурсов — к ограниченному доступу к конкретным ресурсам.

Мастер Ключи

  • Там нет ничего, что вы не можете сделать с мастер-ключом. Вы можете уничтожить всю свою базу данных, если хотите, используя мастер-ключ.

  • По этой причине вам определенно не нужно делиться главным ключом или распространять его в клиентских средах. В качестве дополнительной меры безопасности рекомендуется регулярно менять ее.

  • На самом деле для каждой учетной записи базы данных есть два главных ключа: основной и дополнительный, как показано на снимке экрана выше.

Там нет ничего, что вы не можете сделать с мастер-ключом. Вы можете уничтожить всю свою базу данных, если хотите, используя мастер-ключ.

По этой причине вам определенно не нужно делиться главным ключом или распространять его в клиентских средах. В качестве дополнительной меры безопасности рекомендуется регулярно менять ее.

На самом деле для каждой учетной записи базы данных есть два главных ключа: основной и дополнительный, как показано на снимке экрана выше.

Жетоны ресурса

  • Вы также можете использовать жетоны ресурсов вместо мастер-ключа.

  • Соединения, основанные на токенах ресурсов, могут получать доступ только к ресурсам, указанным токенами, но не к другим ресурсам.

  • Маркеры ресурсов основаны на разрешениях пользователей, поэтому сначала вы создаете одного или нескольких пользователей, и они определяются на уровне базы данных.

  • Вы создаете одно или несколько разрешений для каждого пользователя на основе ресурсов, которые вы хотите разрешить каждому пользователю.

  • Каждое разрешение генерирует маркер ресурса, который разрешает либо только чтение, либо полный доступ к данному ресурсу, и это может быть любой пользовательский ресурс в базе данных.

Вы также можете использовать жетоны ресурсов вместо мастер-ключа.

Соединения, основанные на токенах ресурсов, могут получать доступ только к ресурсам, указанным токенами, но не к другим ресурсам.

Маркеры ресурсов основаны на разрешениях пользователей, поэтому сначала вы создаете одного или нескольких пользователей, и они определяются на уровне базы данных.

Вы создаете одно или несколько разрешений для каждого пользователя на основе ресурсов, которые вы хотите разрешить каждому пользователю.

Каждое разрешение генерирует маркер ресурса, который разрешает либо только чтение, либо полный доступ к данному ресурсу, и это может быть любой пользовательский ресурс в базе данных.

Давайте перейдем к консольному приложению, созданному в главе 3.

Шаг 1 — Добавьте следующие ссылки в файл Program.cs.

using Microsoft.Azure.Documents; 
using Microsoft.Azure.Documents.Client; 
using Microsoft.Azure.Documents.Linq; 
using Newtonsoft.Json;

Шаг 2 — Теперь добавьте URL-адрес конечной точки и ключ авторизации. В этом примере мы будем использовать первичный ключ в качестве ключа авторизации.

Обратите внимание, что в вашем случае URL-адрес конечной точки и ключ авторизации должны отличаться.

private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/"; 
private const string AuthorizationKey = 
   "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";

Шаг 3. Создайте новый экземпляр DocumentClient в асинхронной задаче с именем CreateDocumentClient и создайте экземпляр нового DocumentClient.

Шаг 4 — Вызовите асинхронную задачу из вашего метода Main.

Ниже приведен полный файл Program.cs.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; 
using System.Threading.Tasks;

using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;

namespace DocumentDBDemo { 

   class Program {
      private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
		
      private const string AuthorizationKey = "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/
         StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
			
      static void Main(string[] args) {
         try {
            CreateDocumentClient().Wait();
         } catch (Exception e) {
            Exception baseException = e.GetBaseException();
            Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
         }
			
         Console.ReadKey();
      }
		
      private static async Task CreateDocumentClient() {
         // Create a new instance of the DocumentClient
         var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey);
      }
		
   }
}

В этой главе мы узнали, как подключиться к учетной записи DocumentDB и создать экземпляр класса DocumentClient.

DocumentDB — Создать базу данных

В этой главе мы узнаем, как создать базу данных. Чтобы использовать Microsoft Azure DocumentDB, вы должны иметь учетную запись DocumentDB, базу данных, коллекцию и документы. У нас уже есть учетная запись DocumentDB, теперь для создания базы данных у нас есть два варианта:

  • Портал Microsoft Azure или
  • .Net SDK

Создайте базу данных для DocumentDB, используя портал Microsoft Azure.

Чтобы создать базу данных с использованием портала, выполните следующие действия.

Шаг 1. Войдите на портал Azure, и вы увидите панель управления.

Вход на портал

Шаг 2 — Теперь нажмите на созданную учетную запись DocumentDB, и вы увидите детали, как показано на следующем скриншоте.

нажмите на созданную DocumentDB

Шаг 3 — Выберите опцию Добавить базу данных и укажите идентификатор своей базы данных.

Выберите Добавить базу данных

Шаг 4 — Нажмите ОК.

База данных добавлена

Вы можете видеть, что база данных добавлена. На данный момент у него нет коллекции, но мы можем добавить коллекции позже, которые будут контейнерами для хранения наших документов JSON. Обратите внимание, что у него есть и идентификатор, и идентификатор ресурса.

Создание базы данных для DocumentDB с использованием .Net SDK

Чтобы создать базу данных с помощью .Net SDK, выполните следующие действия.

Шаг 1 — Откройте Консольное приложение в Visual Studio из последней главы.

Шаг 2 — Создайте новую базу данных, создав новый объект базы данных. Чтобы создать новую базу данных, нам нужно только назначить свойство Id, которое мы устанавливаем как «mynewdb» в задаче CreateDatabase.

private async static Task CreateDatabase(DocumentClient client) {
   Console.WriteLine(); 
   Console.WriteLine("******** Create Database *******");
	
   var databaseDefinition = new Database { Id = "mynewdb" }; 
   var result = await client.CreateDatabaseAsync(databaseDefinition); 
   var database = result.Resource;
	
   Console.WriteLine(" Database Id: {0}; Rid: {1}", database.Id, database.ResourceId); 
   Console.WriteLine("******** Database Created *******"); 
} 

Шаг 3 — Теперь передайте это databaseDefinition в CreateDatabaseAsync и получите результат со свойством Resource. Все методы создания объекта возвращают свойство Resource, которое описывает созданный элемент, который в данном случае является базой данных.

Мы получаем новый объект базы данных из свойства Resource, и он отображается на консоли вместе с идентификатором ресурса, который ему назначен DocumentDB.

Шаг 4 — Теперь вызовите задачу CreateDatabase из задачи CreateDocumentClient после создания экземпляра DocumentClient.

using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) { 
   await CreateDatabase(client); 
} 

Ниже приведен полный файл Program.cs.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;

namespace DocumentDBDemo {

   class Program {
      private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
		
      private const string AuthorizationKey = "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/
         StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
			
      static void Main(string[] args) {
         try {
            CreateDocumentClient().Wait();
         } catch (Exception e) {
            Exception baseException = e.GetBaseException();
            Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
         }
         Console.ReadKey();
      }
		
      private static async Task CreateDocumentClient() {
         // Create a new instance of the DocumentClient
         using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
            await CreateDatabase(client);
         } 
      }
		
      private async static Task CreateDatabase(DocumentClient client) {
         Console.WriteLine();
         Console.WriteLine("******** Create Database *******");
			
         var databaseDefinition = new Database { Id = "mynewdb" };
         var result = await client.CreateDatabaseAsync(databaseDefinition);
         var database = result.Resource;
			
         Console.WriteLine(" Database Id: {0}; Rid: {1}", database.Id, database.ResourceId);
         Console.WriteLine("******** Database Created *******");
      }
		
   } 
}

Когда приведенный выше код скомпилирован и выполнен, вы получите следующий вывод, содержащий идентификаторы базы данных и ресурсов.

******** Create Database ******* 
 Database Id: mynewdb; Rid: ltpJAA== 
******** Database Created ******* 

DocumentDB — список баз данных

До сих пор мы создали две базы данных в нашей учетной записи DocumentDB, первая из которых создается с помощью портала Azure, а вторая база данных — с помощью .Net SDK. Теперь для просмотра этих баз данных вы можете использовать портал Azure.

Перейдите в свою учетную запись DocumentDB на портале Azure, и вы увидите две базы данных.

Две базы данных

Вы также можете просматривать или перечислять базы данных из своего кода, используя .Net SDK. Ниже приведены необходимые шаги.

Шаг 1 — Выполните запрос к базе данных без параметров, который возвращает полный список, но вы также можете передать запрос для поиска конкретной базы данных или конкретных баз данных.

private static void GetDatabases(DocumentClient client) {
   Console.WriteLine();
   Console.WriteLine();
   Console.WriteLine("******** Get Databases List ********");
	
   var databases = client.CreateDatabaseQuery().ToList(); 
	
   foreach (var database in databases) { 
      Console.WriteLine(" Database Id: {0}; Rid: {1}", database.Id, database.ResourceId);
   }
	
   Console.WriteLine(); 
   Console.WriteLine("Total databases: {0}", databases.Count);
}

Вы увидите, что существует множество этих методов CreateQuery для поиска коллекций, документов, пользователей и других ресурсов. Эти методы на самом деле не выполняют запрос, они просто определяют запрос и возвращают повторяемый объект.

Это вызов ToList (), который на самом деле выполняет запрос, повторяет результаты и возвращает их в списке.

Шаг 2. Вызов метода GetDatabase из задачи CreateDocumentClient после создания экземпляра DocumentClient.

Шаг 3 — Вам также необходимо прокомментировать задачу CreateDatabase или изменить идентификатор базы данных, в противном случае вы получите сообщение об ошибке, что база данных существует.

using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
   //await CreateDatabase(client); 
   GetDatabases(client); 
}

Ниже приведен полный файл Program.cs.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json; 

namespace DocumentDBDemo {

   class Program {
      private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
		
      private const string AuthorizationKey = "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/
         StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
			
      static void Main(string[] args) {
         try {
            CreateDocumentClient().Wait();
         } catch (Exception e) {
            Exception baseException = e.GetBaseException();
            Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
         }
         Console.ReadKey();
      }
		
      private static async Task CreateDocumentClient() {
         // Create a new instance of the DocumentClient
         using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
            await CreateDatabase(client);
            GetDatabases(client);
         } 
      }
		
      private async static Task CreateDatabase(DocumentClient client) {
         Console.WriteLine();
         Console.WriteLine("******** Create Database *******");
			
         var databaseDefinition = new Database { Id = "mynewdb" };
         var result = await client.CreateDatabaseAsync(databaseDefinition);
         var database = result.Resource;
			
         Console.WriteLine(" Database Id: {0}; Rid: {1}", database.Id, database.ResourceId);
         Console.WriteLine("******** Database Created *******");
      }
		
      private static void GetDatabases(DocumentClient client) {
         Console.WriteLine();
         Console.WriteLine();
         Console.WriteLine("******** Get Databases List ********");
			
         var databases = client.CreateDatabaseQuery().ToList();
			
         foreach (var database in databases) {
            Console.WriteLine(" Database Id: {0}; Rid: {1}",
               database.Id, database.ResourceId);
         }  
			
         Console.WriteLine(); 
         Console.WriteLine("Total databases: {0}", databases.Count);
      }
		
   } 
}

Когда приведенный выше код скомпилирован и выполнен, вы получите следующий вывод, содержащий идентификаторы базы данных и ресурсов обеих баз данных. В конце вы также увидите общее количество баз данных.

******** Get Databases List ******** 
 Database Id: myfirstdb; Rid: Ic8LAA== 
 Database Id: mynewdb; Rid: ltpJAA==  
Total databases: 2 

DocumentDB — отбросить базы данных

Вы можете удалить базу данных или базы данных из портала, а также из кода с помощью .Net SDK. Здесь мы обсудим пошагово, как отбросить базу данных в DocumentDB.

Шаг 1. Перейдите в свою учетную запись DocumentDB на портале Azure. Для демонстрации я добавил еще две базы данных, как показано на следующем снимке экрана.

Удалить базы данных

Шаг 2 — Чтобы удалить любую базу данных, вам нужно щелкнуть эту базу данных. Давайте выберем tempdb, вы увидите следующую страницу, выберите опцию «Удалить базу данных».

Удалить базу данных

Шаг 3 — Появится подтверждающее сообщение, теперь нажмите кнопку «Да».

Подтверждение сообщения

Вы увидите, что база данных tempdb больше не доступна на вашей панели инструментов.

TempDB удален

Вы также можете удалить базы данных из своего кода, используя .Net SDK. Чтобы сделать следующие шаги.

Шаг 1 — Давайте удалим базу данных, указав идентификатор базы данных, которую мы хотим удалить, но нам нужна ее SelfLink.

Шаг 2 — Мы вызываем CreateDatabaseQuery, как и раньше, но на этот раз мы фактически предоставляем запрос, который возвращает только одну базу данных с идентификатором tempdb1.

private async static Task DeleteDatabase(DocumentClient client) {
   Console.WriteLine("******** Delete Database ********");
   Database database = client
      .CreateDatabaseQuery("SELECT * FROM c WHERE c.id = 'tempdb1'")
      .AsEnumerable()
      .First();
   await client.DeleteDatabaseAsync(database.SelfLink);
}

Шаг 3 — На этот раз мы можем вызвать AsEnumerable вместо ToList (), потому что нам на самом деле не нужен объект списка. Ожидая только результата, достаточно вызвать AsEnumerable, чтобы мы могли получить первый объект базы данных, возвращенный запросом с помощью First (). Это объект базы данных для tempdb1, и он имеет SelfLink, который мы можем использовать для вызова DeleteDatabaseAsync, который удаляет базу данных.

Шаг 4. Вам также необходимо вызвать задачу DeleteDatabase из задачи CreateDocumentClient после создания экземпляра DocumentClient.

Шаг 5 — Чтобы просмотреть список баз данных после удаления указанной базы данных, давайте снова вызовем метод GetDatabases.

using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
   //await CreateDatabase(client);
	
   GetDatabases(client);
   await DeleteDatabase(client);
   GetDatabases(client); 
} 

Ниже приведен полный файл Program.cs.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;

namespace DocumentDBDemo {

   class Program {
	
      private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
		
      private const string AuthorizationKey = "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/
         StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
			
      static void Main(string[] args) {
         try {
            CreateDocumentClient().Wait();
         } catch (Exception e) {
            Exception baseException = e.GetBaseException();
            Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
         }
         Console.ReadKey();
      }
		
      private static async Task CreateDocumentClient() {
         // Create a new instance of the DocumentClient
         using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
            //await CreateDatabase(client);
            GetDatabases(client);
            await DeleteDatabase(client);
            GetDatabases(client);
         }
      }
		
      private async static Task CreateDatabase(DocumentClient client) {
         Console.WriteLine();
         Console.WriteLine("******** Create Database *******");
			
         var databaseDefinition = new Database { Id = "mynewdb" };
         var result = await client.CreateDatabaseAsync(databaseDefinition);
         var database = result.Resource;
			
         Console.WriteLine(" Database Id: {0}; Rid: {1}",
            database.Id, database.ResourceId);
         Console.WriteLine("******** Database Created *******");
      }
		
      private static void GetDatabases(DocumentClient client) {
         Console.WriteLine();
         Console.WriteLine();
         Console.WriteLine("******** Get Databases List ********");
			
         var databases = client.CreateDatabaseQuery().ToList();
			
         foreach (var database in databases) {
            Console.WriteLine(" Database Id: {0}; Rid: {1}", database.Id,
               database.ResourceId);
         }
			
         Console.WriteLine();
         Console.WriteLine("Total databases: {0}", databases.Count);
      }
		
      private async static Task DeleteDatabase(DocumentClient client) {
         Console.WriteLine();
         Console.WriteLine("******** Delete Database ********");
			
         Database database = client
            .CreateDatabaseQuery("SELECT * FROM c WHERE c.id = 'tempdb1'")
            .AsEnumerable()
            .First();
         await client.DeleteDatabaseAsync(database.SelfLink);
      }
		
   }
}

Когда приведенный выше код скомпилирован и выполнен, вы получите следующий вывод, содержащий идентификаторы базы данных и ресурсов трех баз данных и общее количество баз данных.

******** Get Databases List ******** 
 Database Id: myfirstdb; Rid: Ic8LAA== 
 Database Id: mynewdb; Rid: ltpJAA== 
 Database Id: tempdb1; Rid: 06JjAA==
 
Total databases: 3  

******** Delete Database ******** 
  
******** Get Databases List ******** 
 Database Id: myfirstdb; Rid: Ic8LAA== 
 Database Id: mynewdb; Rid: ltpJAA==
 
Total databases: 2 

После удаления базы данных в конце вы также увидите, что в учетной записи DocumentDB остались только две базы данных.

DocumentDB — Создать коллекцию

В этой главе мы узнаем, как создать коллекцию. Это похоже на создание базы данных. Вы можете создать коллекцию либо из портала, либо из кода, используя .Net SDK.

Шаг 1. Перейдите на главную панель инструментов на портале Azure.

Создать коллекцию

Шаг 2 — Выберите myfirstdb из списка баз данных.

myfirstdb

Шаг 3 — Нажмите на опцию «Добавить коллекцию» и укажите идентификатор для коллекции. Выберите уровень цен для другого варианта.

Добавить коллекцию

Шаг 4 — Давайте выберем S1 Standard и нажмите «Выбрать» → кнопку «ОК».

выберите S1 Standard

Как вы можете видеть, MyCollection добавлен в myfirstdb.

Вы также можете создать коллекцию из кода с помощью .Net SDK. Давайте посмотрим на следующие шаги, чтобы добавить коллекции из кода.

Шаг 1 — Откройте консольное приложение в Visual Studio.

Шаг 2. Чтобы создать коллекцию, сначала получите базу данных myfirstdb по ее идентификатору в задаче CreateDocumentClient.

private static async Task CreateDocumentClient() {

   // Create a new instance of the DocumentClient
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
      database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
         'myfirstdb'").AsEnumerable().First();
			
      await CreateCollection(client, "MyCollection1");
      await CreateCollection(client, "MyCollection2", "S2"); 
   }
}

Ниже приведена реализация задачи CreateCollection.

private async static Task CreateCollection(DocumentClient client, string collectionId,
   string offerType = "S1") {
	
   Console.WriteLine();
   Console.WriteLine("**** Create Collection {0} in {1} ****", collectionId, database.Id);
	
   var collectionDefinition = new DocumentCollection { Id = collectionId };
   var options = new RequestOptions { OfferType = offerType };
   var result = await client.CreateDocumentCollectionAsync(database.SelfLink,
      collectionDefinition, options);
   var collection = result.Resource;
	
   Console.WriteLine("Created new collection");
   ViewCollection(collection);
}

Мы создаем новый объект DocumentCollection, который определяет новую коллекцию с требуемым идентификатором для метода CreateDocumentCollectionAsync, который также принимает параметр параметров, который мы используем здесь, чтобы установить уровень производительности новой коллекции, который мы называем offerType.

По умолчанию это S1, и, поскольку мы не передали offerType для MyCollection1, то есть это будет коллекция S1, а для MyCollection2 мы передали S2, что делает его S2, как показано выше.

Ниже приведена реализация метода ViewCollection.

private static void ViewCollection(DocumentCollection collection) {
   Console.WriteLine("Collection ID: {0} ", collection.Id); 
   Console.WriteLine("Resource ID: {0} ", collection.ResourceId); 
   Console.WriteLine("Self Link: {0} ", collection.SelfLink); 
   Console.WriteLine("Documents Link: {0} ", collection.DocumentsLink); 
   Console.WriteLine("UDFs Link: {0} ", collection.UserDefinedFunctionsLink); 
   Console.WriteLine(" StoredProcs Link: {0} ", collection.StoredProceduresLink); 
   Console.WriteLine("Triggers Link: {0} ", collection.TriggersLink); 
   Console.WriteLine("Timestamp: {0} ", collection.Timestamp);
}

Ниже приводится полная реализация файла program.cs для коллекций.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;

using Newtonsoft.Json;

namespace DocumentDBDemo {

   class Program {
	
      private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
		
      private const string AuthorizationKey = "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/
         StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
			
      private static Database database;
		
      static void Main(string[] args) {
         try {
            CreateDocumentClient().Wait();
         } catch (Exception e) {
            Exception baseException = e.GetBaseException();
            Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
         }
         Console.ReadKey();
      }
		
      private static async Task CreateDocumentClient() {
         // Create a new instance of the DocumentClient
         using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
            database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
               'myfirstdb'").AsEnumerable().First();
            await CreateCollection(client, "MyCollection1");
            await CreateCollection(client, "MyCollection2", "S2");
				
            //await CreateDatabase(client);
            //GetDatabases(client);
            //await DeleteDatabase(client);
            //GetDatabases(client);
         }
      }
		
      private async static Task CreateCollection(DocumentClient client,
         string collectionId, string offerType = "S1") {
			
         Console.WriteLine();
         Console.WriteLine("**** Create Collection {0} in {1} ****", collectionId,
            database.Id);

         var collectionDefinition = new DocumentCollection { Id = collectionId };
         var options = new RequestOptions { OfferType = offerType };
         var result = await 
			
			client.CreateDocumentCollectionAsync(database.SelfLink,
            collectionDefinition, options);
         var collection = result.Resource;

         Console.WriteLine("Created new collection");
         ViewCollection(collection);
      }
		
      private static void ViewCollection(DocumentCollection collection) {
         Console.WriteLine("Collection ID: {0} ", collection.Id);
         Console.WriteLine("Resource ID: {0} ", collection.ResourceId);
         Console.WriteLine("Self Link: {0} ", collection.SelfLink);
         Console.WriteLine("Documents Link: {0} ", collection.DocumentsLink);
         Console.WriteLine("UDFs Link: {0} ", collection.UserDefinedFunctionsLink);
         Console.WriteLine("StoredProcs Link: {0} ", collection.StoredProceduresLink);
         Console.WriteLine("Triggers Link: {0} ", collection.TriggersLink);
         Console.WriteLine("Timestamp: {0} ", collection.Timestamp);
      }
		
   }
}

Когда приведенный выше код скомпилирован и выполнен, вы получите следующий вывод, который содержит всю информацию, касающуюся сбора.

**** Create Collection MyCollection1 in myfirstdb **** 
Created new collection
   Collection ID: MyCollection1
      Resource ID: Ic8LAPPvnAA=
         Self Link: dbs/Ic8LAA==/colls/Ic8LAPPvnAA=/
   Documents Link: dbs/Ic8LAA==/colls/Ic8LAPPvnAA=/docs/
         UDFs Link: dbs/Ic8LAA==/colls/Ic8LAPPvnAA=/udfs/
   StoredProcs Link: dbs/Ic8LAA==/colls/Ic8LAPPvnAA=/sprocs/
      Triggers Link: dbs/Ic8LAA==/colls/Ic8LAPPvnAA=/triggers/
         Timestamp: 12/10/2015 4:55:36 PM
		  
**** Create Collection MyCollection2 in myfirstdb ****
Created new collection
   Collection ID: MyCollection2
      Resource ID: Ic8LAKGHDwE=
         Self Link: dbs/Ic8LAA==/colls/Ic8LAKGHDwE=/
   Documents Link: dbs/Ic8LAA==/colls/Ic8LAKGHDwE=/docs/
         UDFs Link: dbs/Ic8LAA==/colls/Ic8LAKGHDwE=/udfs/
   StoredProcs Link: dbs/Ic8LAA==/colls/Ic8LAKGHDwE=/sprocs/
      Triggers Link: dbs/Ic8LAA==/colls/Ic8LAKGHDwE=/triggers/
         Timestamp: 12/10/2015 4:55:38 PM

DocumentDB — Удалить коллекцию

Чтобы удалить коллекцию или коллекции, вы можете сделать то же самое из портала, а также из кода с помощью .Net SDK.

Шаг 1. Перейдите в свою учетную запись DocumentDB на портале Azure. Для демонстрации я добавил еще две коллекции, как показано на следующем скриншоте.

Удалить коллекцию

Шаг 2 — Чтобы удалить любую коллекцию, вам нужно нажать на эту коллекцию. Давайте выберем TempCollection1. Вы увидите следующую страницу, выберите опцию «Удалить коллекцию».

Выберите коллекцию

Шаг 3 — Появится подтверждающее сообщение. Теперь нажмите кнопку «Да».

Удалить коллекционное сообщение

Вы увидите, что TempCollection1 больше не доступен на вашей панели.

Коллекция удалена

Вы также можете удалить коллекции из своего кода, используя .Net SDK. Для этого выполните следующие шаги.

Шаг 1 — Давайте удалим коллекцию, указав идентификатор коллекции, которую мы хотим удалить.

Это обычный шаблон запросов по Id для получения selfLinks, необходимых для удаления ресурса.

private async static Task DeleteCollection(DocumentClient client, string collectionId) {
   Console.WriteLine();
   Console.WriteLine("**** Delete Collection {0} in {1} ****", collectionId, database.Id);
	
   var query = new SqlQuerySpec {
      QueryText = "SELECT * FROM c WHERE c.id = @id",
         Parameters = new SqlParameterCollection {
         new SqlParameter {
            Name = "@id", Value = collectionId
         }
      }
   };
	
   DocumentCollection collection = client.CreateDocumentCollectionQuery(database.SelfLink,
      query).AsEnumerable().First();
		
   await client.DeleteDocumentCollectionAsync(collection.SelfLink);
   Console.WriteLine("Deleted collection {0} from database {1}", collectionId,
      database.Id);
}

Здесь мы видим предпочтительный способ построения параметризованного запроса. Мы не кодируем collectionId, поэтому этот метод можно использовать для удаления любой коллекции. Мы запрашиваем конкретную коллекцию по Id, где параметр Id определен в этой коллекции SqlParameterCollection, назначенной свойству параметра этой SqlQuerySpec.

Затем SDK выполняет работу по созданию окончательной строки запроса для DocumentDB с встроенным в нее collectionId.

Шаг 2. Запустите запрос и затем используйте его SelfLink для удаления коллекции из задачи CreateDocumentClient.

private static async Task CreateDocumentClient() {
   // Create a new instance of the DocumentClient 
	
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
      database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
         'myfirstdb'").AsEnumerable().First(); 
      await DeleteCollection(client, "TempCollection"); 
   } 
}

Ниже приведена полная реализация файла Program.cs.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;

using Newtonsoft.Json;

namespace DocumentDBDemo {

   class Program {
	
      private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
		
      private const string AuthorizationKey = "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/
         StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
			
      private static Database database;

      static void Main(string[] args) {
         try {
            CreateDocumentClient().Wait();
         } catch (Exception e) {
            Exception baseException = e.GetBaseException();
            Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
         }
         Console.ReadKey();
      }

      private static async Task CreateDocumentClient() {
         // Create a new instance of the DocumentClient
         using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
            database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
               'myfirstdb'").AsEnumerable().First();
            await DeleteCollection(client, "TempCollection");
				
            //await CreateCollection(client, "MyCollection1");
            //await CreateCollection(client, "MyCollection2", "S2");
            ////await CreateDatabase(client);
            //GetDatabases(client);
            //await DeleteDatabase(client);
            //GetDatabases(client);
         }
      }
		
      private async static Task CreateCollection(DocumentClient client,
         string collectionId, string offerType = "S1") {
			
         Console.WriteLine();
         Console.WriteLine("**** Create Collection {0} in {1} ****", collectionId,
            database.Id);
         
         var collectionDefinition = new DocumentCollection { Id = collectionId };
         var options = new RequestOptions { OfferType = offerType };
         var result = await client.CreateDocumentCollectionAsync(database.SelfLink,
            collectionDefinition, options);
				
         var collection = result.Resource; 
         
         Console.WriteLine("Created new collection"); 
         ViewCollection(collection); 
      }

      private static void ViewCollection(DocumentCollection collection) {
         Console.WriteLine("Collection ID: {0} ", collection.Id); 
         Console.WriteLine("Resource ID: {0} ", collection.ResourceId); 
         Console.WriteLine("Self Link: {0} ", collection.SelfLink); 
         Console.WriteLine("Documents Link: {0} ", collection.DocumentsLink); 
         Console.WriteLine("UDFs Link: {0} ", collection.UserDefinedFunctionsLink); 
         Console.WriteLine("StoredProcs Link: {0} ", collection.StoredProceduresLink); 
         Console.WriteLine("Triggers Link: {0} ", collection.TriggersLink); 
         Console.WriteLine("Timestamp: {0} ", collection.Timestamp); 
      }
		
      private async static Task DeleteCollection(DocumentClient client,
         string collectionId) {
			
         Console.WriteLine();
         Console.WriteLine("**** Delete Collection {0} in {1} ****", collectionId,
            database.Id);
				
         var query = new SqlQuerySpec {
            QueryText = "SELECT * FROM c WHERE c.id = @id", Parameters = new
               SqlParameterCollection {
               new SqlParameter {
                  Name = "@id", Value = collectionId
               }
            }
         };
			
         DocumentCollection collection = client.CreateDocumentCollectionQuery
            (database.SelfLink, query).AsEnumerable().First();
				
         await client.DeleteDocumentCollectionAsync(collection.SelfLink);
         Console.WriteLine("Deleted collection {0} from database {1}", collectionId,
            database.Id); 
      }
		
   } 
}

Когда приведенный выше код скомпилирован и выполнен, вы получите следующий вывод.

**** Delete Collection TempCollection in myfirstdb **** 
Deleted collection TempCollection from database myfirstdb

DocumentDB — Вставить документ

В этой главе мы приступим к работе с актуальными документами в коллекции. Вы можете создавать документы, используя портал Azure или .Net SDK.

Создание документов с помощью портала Azure

Давайте посмотрим на следующие шаги, чтобы добавить документ в вашу коллекцию.

Шаг 1 — Добавить новую коллекцию Семейный ценовой уровень S1 в myfirstdb.

Вставить документ

Шаг 2 — Выберите коллекцию Families и нажмите опцию Create Document, чтобы открыть блейд New Document.

Семейная коллекция

Это простой текстовый редактор, который позволяет вам вводить любой JSON для нового документа.

простой текстовый редактор

Шаг 3 — Поскольку это ввод необработанных данных, давайте введем наш первый документ.

{
   "id": "AndersenFamily", 
   "lastName": "Andersen", 
	
   "parents": [ 
      { "firstName": "Thomas", "relationship": "father" }, 
      { "firstName": "Mary Kay", "relationship": "mother" } 
   ], 
	
   "children": [ 
      { 
         "firstName": "Henriette Thaulow", 
         "gender": "female", 
         "grade": 5, 
         "pets": [ { "givenName": "Fluffy", "type": "Rabbit" } ] 
      } 
   ], 
	
   "location": { "state": "WA", "county": "King", "city": "Seattle"}, 
   "isRegistered": true
}

Когда вы введете вышеуказанный документ, вы увидите следующий экран.

Документ

Обратите внимание, что мы предоставили идентификатор для документа. Значение id всегда требуется, и оно должно быть уникальным для всех других документов в той же коллекции. Когда вы его пропустите, DocumentDB автоматически сгенерирует его для вас, используя GUID или глобальный уникальный идентификатор.

Идентификатор всегда является строкой и не может быть числом, датой, логическим или другим объектом и не может быть длиннее 255 символов.

Также обратите внимание на иерархическую структуру документа, которая имеет несколько свойств верхнего уровня, таких как обязательный идентификатор, а также lastName и isRegistered, но также имеет вложенные свойства.

Например, свойство parent предоставляется в виде массива JSON, обозначенного квадратными скобками. У нас также есть другой массив для дочерних элементов, хотя в этом примере есть только один дочерний массив.

Шаг 4 — Нажмите кнопку «Сохранить», чтобы сохранить документ, и мы создали наш первый документ.

Как вы можете видеть, к нашему JSON было применено симпатичное форматирование, которое разбивает каждое свойство на отдельной строке с пробелами для передачи уровня вложенности каждого свойства.

Сохранить документ

Портал включает в себя проводник документов, поэтому давайте теперь воспользуемся им для получения только что созданного документа.

Получить документ

Шаг 5 — Выберите базу данных и любую коллекцию в базе данных, чтобы просмотреть документы в этой коллекции. В настоящее время у нас есть только одна база данных myfirstdb с одной коллекцией под названием Families, обе из которых были предварительно выбраны здесь в выпадающих списках.

выберите базу данных

По умолчанию в обозревателе документов отображается нефильтрованный список документов в коллекции, но вы также можете выполнить поиск любого конкретного документа по идентификатору или по нескольким документам на основе поиска по частичному идентификатору частичного идентификатора.

Пока у нас есть только один документ в нашей коллекции, и мы видим его идентификатор на следующем экране, AndersonFamily.

Шаг 6 — Нажмите на идентификатор, чтобы просмотреть документ.

Нажмите на ID

Создание документов с помощью .NET SDK

Как вы знаете, документы — это просто другой тип ресурса, и вы уже познакомились с тем, как обращаться с ресурсами с помощью SDK.

  • Одно большое различие между документами и другими ресурсами заключается в том, что они, разумеется, не содержат схем.

  • Таким образом, вариантов много. Естественно, вы можете просто работать с графами объектов JSON или даже с необработанными строками текста JSON, но вы также можете использовать динамические объекты, которые позволяют связывать свойства во время выполнения, не определяя класс во время компиляции.

  • Вы также можете работать с реальными объектами C # или объектами, как они называются, которые могут быть классами вашего бизнес-домена.

Одно большое различие между документами и другими ресурсами заключается в том, что они, разумеется, не содержат схем.

Таким образом, вариантов много. Естественно, вы можете просто работать с графами объектов JSON или даже с необработанными строками текста JSON, но вы также можете использовать динамические объекты, которые позволяют связывать свойства во время выполнения, не определяя класс во время компиляции.

Вы также можете работать с реальными объектами C # или объектами, как они называются, которые могут быть классами вашего бизнес-домена.

Давайте начнем создавать документы с использованием .Net SDK. Ниже приведены шаги.

Шаг 1 — Создайте экземпляр DocumentClient, затем мы запросим базу данных myfirstdb, а затем запросим коллекцию MyCollection, которую мы храним в этой коллекции частных переменных, чтобы она была доступна всему классу.

private static async Task CreateDocumentClient() {
   // Create a new instance of the DocumentClient
	
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
      database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
         'myfirstdb'").AsEnumerable().First(); 
			
      collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
         "SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();  
			
      await CreateDocuments(client); 
   } 
}

Шаг 2 — Создайте несколько документов в задаче CreateDocuments.

private async static Task CreateDocuments(DocumentClient client) {
   Console.WriteLine(); 
   Console.WriteLine("**** Create Documents ****"); 
   Console.WriteLine();
	
   dynamic document1Definition = new {
      name = "New Customer 1", address = new {
         addressType = "Main Office", 
         addressLine1 = "123 Main Street", 
         location = new {
            city = "Brooklyn", stateProvinceName = "New York" 
         }, postalCode = "11229", countryRegionName = "United States"
      }, 
   };
	
   Document document1 = await CreateDocument(client, document1Definition); 
   Console.WriteLine("Created document {0} from dynamic object", document1.Id); 
   Console.WriteLine(); 
} 

Первый документ будет создан из этого динамического объекта. Это может выглядеть как JSON, но, конечно, это не так. Это код C #, и мы создаем настоящий объект .NET, но нет определения класса. Вместо этого свойства выводятся из способа инициализации объекта.

Обратите внимание, что мы не предоставили свойство Id для этого документа.

Теперь давайте посмотрим на CreateDocument. Похоже на тот же шаблон, который мы видели при создании баз данных и коллекций.

private async static Task<Document> CreateDocument(DocumentClient client,
   object documentObject) {
	
   var result = await client.CreateDocumentAsync(collection.SelfLink, documentObject); 
   var document = result.Resource;
	
   Console.WriteLine("Created new document: {0}\r\n{1}", document.Id, document); 
   return result; 
}

Шаг 3 — На этот раз мы вызываем CreateDocumentAsync, определяя SelfLink коллекции, в которую мы хотим добавить документ. Мы получаем ответ со свойством ресурса, которое в данном случае представляет новый документ с его сгенерированными системой свойствами.

Объект Document — это определенный класс в SDK, который наследуется от ресурса и поэтому имеет все общие свойства ресурса, но также включает в себя динамические свойства, которые определяют сам документ без схемы.

private async static Task CreateDocuments(DocumentClient client) {
   Console.WriteLine(); 
   Console.WriteLine("**** Create Documents ****"); 
   Console.WriteLine();  
	
   dynamic document1Definition = new {
      name = "New Customer 1", address = new { 
         addressType = "Main Office",
         addressLine1 = "123 Main Street", 
         location = new {
            city = "Brooklyn", stateProvinceName = "New York" 
         }, postalCode = "11229", countryRegionName = "United States" 
      }, 
   };
	
   Document document1 = await CreateDocument(client, document1Definition); 
   Console.WriteLine("Created document {0} from dynamic object", document1.Id); 
   Console.WriteLine();
}

Когда приведенный выше код скомпилирован и выполнен, вы получите следующий вывод.

**** Create Documents ****  
Created new document: 34e9873a-94c8-4720-9146-d63fb7840fad {
   "name": "New Customer 1", 
	
   "address": { 
      "addressType": "Main Office", 
      "addressLine1": "123 Main Street", 
      "location": { 
         "city": "Brooklyn", "stateProvinceName": "New York" 
      }, 
      "postalCode": "11229", "countryRegionName": "United States"
   }, 
	
   "id": "34e9873a-94c8-4720-9146-d63fb7840fad", 
   "_rid": "Ic8LAMEUVgACAAAAAAAAAA==", 
   "_ts": 1449812756, 
   "_self": "dbs/Ic8LAA==/colls/Ic8LAMEUVgA=/docs/Ic8LAMEUVgACAAAAAAAAAA==/", 
   "_etag": "\"00001000-0000-0000-0000-566a63140000\"", 
   "_attachments": "attachments/" 
} 
Created document 34e9873a-94c8-4720-9146-d63fb7840fad from dynamic object 

Как вы можете видеть, мы не предоставили Id, однако DocumentDB сгенерировал его для нас для нового документа.

DocumentDB — Запрос документа

В DocumentDB мы фактически используем SQL для запроса документов, так что эта глава посвящена запросам с использованием специального синтаксиса SQL в DocumentDB. Хотя, если вы занимаетесь разработкой .NET, есть также поставщик LINQ, который можно использовать и который может генерировать соответствующий SQL из запроса LINQ.

Запрос документа с помощью портала

На портале Azure есть Query Explorer, который позволяет вам выполнять любые SQL-запросы к базе данных DocumentDB.

Мы будем использовать Query Explorer, чтобы продемонстрировать множество различных возможностей и возможностей языка запросов, начиная с самого простого запроса.

Шаг 1 — В блейде базы данных щелкните, чтобы открыть блейд Query Explorer.

Query Explorer Blade

Помните, что запросы выполняются в рамках коллекции, поэтому Query Explorer позволяет выбрать коллекцию в этом раскрывающемся списке.

Запустить запрос

Шаг 2 — Выберите коллекцию Families, которая была создана ранее с использованием портала.

Query Explorer открывается с этим простым запросом SELECT * FROM c, который просто извлекает все документы из коллекции.

Шаг 3 — Выполните этот запрос, нажав кнопку «Выполнить запрос». Затем вы увидите, что весь документ получен в колонке результатов.

Документ в результирующем блейде

Запрос документа с использованием .Net SDK

Ниже приведены шаги для запуска некоторых запросов документов с использованием .Net SDK.

В этом примере мы хотим запросить только что добавленные документы.

Шаг 1. Вызовите CreateDocumentQuery, передав коллекцию для выполнения запроса по ее SelfLink и тексту запроса.

private async static Task QueryDocumentsWithPaging(DocumentClient client) {
   Console.WriteLine(); 
   Console.WriteLine("**** Query Documents (paged results) ****"); 
   Console.WriteLine();  
   Console.WriteLine("Quering for all documents"); 
	
   var sql = "SELECT * FROM c";  
   var query = client.CreateDocumentQuery(collection.SelfLink, sql).AsDocumentQuery();
	
   while (query.HasMoreResults) {
      var documents = await query.ExecuteNextAsync(); 
		
      foreach (var document in documents) { 
         Console.WriteLine(" Id: {0}; Name: {1};", document.id, document.name); 
      } 
   }
	
   Console.WriteLine(); 
} 

Этот запрос также возвращает все документы во всей коллекции, но мы не вызываем .ToList для CreateDocumentQuery, как раньше, который бы выдавал столько запросов, сколько необходимо для вывода всех результатов в одну строку кода.

Шаг 2 — Вместо этого вызовите AsDocumentQuery, и этот метод возвращает объект запроса со свойством HasMoreResults.

Шаг 3. Если значение HasMoreResults равно true, вызовите ExecuteNextAsync, чтобы получить следующий фрагмент, а затем выведите все содержимое этого фрагмента.

Шаг 4 — Вы также можете запросить, используя LINQ вместо SQL, если хотите. Здесь мы определили запрос LINQ в q, но он не будет выполняться, пока мы не запустим .ToList для него.

private static void QueryDocumentsWithLinq(DocumentClient client) {
   Console.WriteLine(); 
   Console.WriteLine("**** Query Documents (LINQ) ****"); 
   Console.WriteLine();  
   Console.WriteLine("Quering for US customers (LINQ)");
	
   var q = 
      from d in client.CreateDocumentQuery<Customer>(collection.DocumentsLink) 
      where d.Address.CountryRegionName == " United States" 
      select new {
         Id = d.Id, 
         Name = d.Name, 
         City = d.Address.Location.City 
      };  
		
   var documents = q.ToList();  
   Console.WriteLine("Found {0} UK customers", documents.Count);
	
   foreach (var document in documents) {
      var d = document as dynamic; 
      Console.WriteLine(" Id: {0}; Name: {1}; City: {2}", d.Id, d.Name, d.City); 
   } 
	
   Console.WriteLine(); 
}

SDK преобразует наш запрос LINQ в синтаксис SQL для DocumentDB, генерируя предложение SELECT и WHERE на основе нашего синтаксиса LINQ.

Шаг 5 — Теперь вызовите вышеупомянутые запросы из задачи CreateDocumentClient.

private static async Task CreateDocumentClient() { 
   // Create a new instance of the DocumentClient 
	
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
      database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
         'myfirstdb'").AsEnumerable().First(); 
			
      collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
         "SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();  
			
      //await CreateDocuments(client); 
      await QueryDocumentsWithPaging(client); 
      QueryDocumentsWithLinq(client); 
   } 
	
}

Когда приведенный выше код будет выполнен, вы получите следующий вывод.

**** Query Documents (paged results) ****  
Quering for all documents 
 Id: 7e9ad4fa-c432-4d1a-b120-58fd7113609f; Name: New Customer 1; 
 Id: 34e9873a-94c8-4720-9146-d63fb7840fad; Name: New Customer 1;  
 
**** Query Documents (LINQ) **** 
Quering for US customers (LINQ) 
Found 2 UK customers 
 Id: 7e9ad4fa-c432-4d1a-b120-58fd7113609f; Name: New Customer 1; City: Brooklyn 
 Id: 34e9873a-94c8-4720-9146-d63fb7840fad; Name: New Customer 1; City: Brooklyn

DocumentDB — обновить документ

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

Обновить документ

Нажмите кнопку «Сохранить». Теперь, когда вам нужно изменить документ с помощью .Net SDK, вы можете просто заменить его. Вам не нужно удалять и воссоздавать его, что, помимо утомления, также приведет к изменению идентификатора ресурса, чего не стоит делать при изменении документа. Вот следующие шаги для обновления документа с помощью .Net SDK.

Давайте посмотрим на следующую задачу ReplaceDocuments, где мы будем запрашивать документы, для которых свойство isNew имеет значение true, но мы не получим ни одного, потому что их нет. Итак, давайте изменим документы, которые мы добавили ранее, те, чьи имена начинаются с New Customer.

Шаг 1 — Добавьте свойство isNew к этим документам и установите для него значение true.

private async static Task ReplaceDocuments(DocumentClient client) {

   Console.WriteLine(); 
   Console.WriteLine(">>> Replace Documents <<<"); 
   Console.WriteLine();  
   Console.WriteLine("Quering for documents with 'isNew' flag");
	
   var sql = "SELECT * FROM c WHERE c.isNew = true"; 
   var documents = client.CreateDocumentQuery(collection.SelfLink, sql).ToList();
	
   Console.WriteLine("Documents with 'isNew' flag: {0} ", documents.Count); 
   Console.WriteLine();  
   Console.WriteLine("Quering for documents to be updated"); 
	
   sql = "SELECT * FROM c WHERE STARTSWITH(c.name, 'New Customer') = true"; 
   documents = client.CreateDocumentQuery(collection.SelfLink, sql).ToList(); 
   Console.WriteLine("Found {0} documents to be updated", documents.Count); 
	
   foreach (var document in documents) {
      document.isNew = true; 
      var result = await client.ReplaceDocumentAsync(document._self, document); 
      var updatedDocument = result.Resource; 
      Console.WriteLine("Updated document 'isNew' flag: {0}", updatedDocument.isNew); 
   }
	
   Console.WriteLine();  
   Console.WriteLine("Quering for documents with 'isNew' flag");
	
   sql = "SELECT * FROM c WHERE c.isNew = true"; 
   documents = client.CreateDocumentQuery(collection.SelfLink, sql).ToList(); 
   Console.WriteLine("Documents with 'isNew' flag: {0}: ", documents.Count); 
   Console.WriteLine(); 
}

Шаг 2 — Получить документы, которые будут обновлены, используя тот же запрос STARTSWITH, и это дает нам документы, которые мы возвращаем сюда как динамические объекты.

Шаг 3 — Присоедините свойство isNew и установите для него значение true для каждого документа.

Шаг 4 — Вызовите ReplaceDocumentAsync, передавая SelfLink документа вместе с обновленным документом.

Теперь, чтобы доказать, что это сработало, запросите документы, где isNew равно true. Давайте вызовем вышеупомянутые запросы из задачи CreateDocumentClient.

private static async Task CreateDocumentClient() {
   // Create a new instance of the DocumentClient
	
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
      database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
         'myfirstdb'").AsEnumerable().First(); 
			
      collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
         "SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();
			
      //await CreateDocuments(client);  
      //QueryDocumentsWithSql(client); 
      //await QueryDocumentsWithPaging(client); 
      //QueryDocumentsWithLinq(client); 
      await ReplaceDocuments(client); 
   }
	
}

Когда приведенный выше код скомпилирован и выполнен, вы получите следующий вывод.

**** Replace Documents ****  
Quering for documents with 'isNew' flag 
Documents with 'isNew' flag: 0 
Quering for documents to be updated 
Found 2 documents to be updated 
Updated document ‘isNew’ flag: True 
Updated document ‘isNew’ flag: True 
Quering for documents with 'isNew' flag 
Documents with 'isNew' flag: 2 

DocumentDB — Удалить документ

В этой главе мы узнаем, как удалить документ из вашей учетной записи DocumentDB. Используя портал Azure, вы можете легко удалить любой документ, открыв его в проводнике и выбрав «Удалить».

Удалить документ

Диалог удаления документа

Появится подтверждающее сообщение. Теперь нажмите кнопку Да, и вы увидите, что документ больше не доступен в вашей учетной записи DocumentDB.

Теперь, когда вы хотите удалить документ с помощью .Net SDK.

Шаг 1 — Это тот же шаблон, который мы видели ранее, где мы сначала запросим, ​​чтобы получить SelfLinks каждого нового документа. Мы не используем SELECT * здесь, что бы вернуть документы в полном объеме, что нам не нужно.

Шаг 2. Вместо этого мы просто выбираем SelfLinks в список, а затем просто вызываем DeleteDocumentAsync для каждого SelfLink, по одному, чтобы удалить документы из коллекции.

private async static Task DeleteDocuments(DocumentClient client) {
   Console.WriteLine();
   Console.WriteLine(">>> Delete Documents <<<");
   Console.WriteLine();
   Console.WriteLine("Quering for documents to be deleted");
	
   var sql =
      "SELECT VALUE c._self FROM c WHERE STARTSWITH(c.name, 'New Customer') = true";
		
   var documentLinks =
      client.CreateDocumentQuery<string>(collection.SelfLink, sql).ToList();
		
   Console.WriteLine("Found {0} documents to be deleted", documentLinks.Count);

   foreach (var documentLink in documentLinks) {
      await client.DeleteDocumentAsync(documentLink);
   }
	
   Console.WriteLine("Deleted {0} new customer documents", documentLinks.Count);
   Console.WriteLine();
}

Шаг 3 — Теперь давайте вызовем вышеупомянутые DeleteDocuments из задачи CreateDocumentClient.

private static async Task CreateDocumentClient() {
   // Create a new instance of the DocumentClient 
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
      database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
         'myfirstdb'").AsEnumerable().First(); 
			
      collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
         "SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();  
			
      await DeleteDocuments(client); 
   } 
}

Когда приведенный выше код будет выполнен, вы получите следующий вывод.

***** Delete Documents *****  
Quering for documents to be deleted 
Found 2 documents to be deleted 
Deleted 2 new customer documents 

DocumentDB — Моделирование данных

В то время как базы данных без схемы, такие как DocumentDB, упрощают внесение изменений в вашу модель данных, вам все равно придется потратить некоторое время на обдумывание своих данных.

  • У вас есть много вариантов. Естественно, вы можете просто работать с графами объектов JSON или даже с необработанными строками текста JSON, но вы также можете использовать динамические объекты, которые позволяют связывать свойства во время выполнения, не определяя класс во время компиляции.

  • Вы также можете работать с реальными объектами C # или объектами, как они называются, которые могут быть классами вашего бизнес-домена.

У вас есть много вариантов. Естественно, вы можете просто работать с графами объектов JSON или даже с необработанными строками текста JSON, но вы также можете использовать динамические объекты, которые позволяют связывать свойства во время выполнения, не определяя класс во время компиляции.

Вы также можете работать с реальными объектами C # или объектами, как они называются, которые могут быть классами вашего бизнес-домена.

Отношения

Давайте посмотрим на иерархическую структуру документа. Он имеет несколько свойств верхнего уровня, таких как обязательный идентификатор, а также lastName и isRegistered, но также имеет вложенные свойства.

{ 
   "id": "AndersenFamily", 
   "lastName": "Andersen", 
	
   "parents": [ 
      { "firstName": "Thomas", "relationship": "father" }, 
      { "firstName": "Mary Kay", "relationship": "mother" } 
   ],
	
   "children": [ 
      { 
         "firstName": "Henriette Thaulow", 
         "gender": "female", 
         "grade": 5, 
         "pets": [ { "givenName": "Fluffy", "type": "Rabbit" } ] 
      } 
   ], 
	
   "location": { "state": "WA", "county": "King", "city": "Seattle"}, 
   "isRegistered": true 
}
  • Например, свойство parent предоставляется в виде массива JSON, обозначенного квадратными скобками.

  • У нас также есть другой массив для дочерних элементов, хотя в этом примере есть только один дочерний массив. Вот как вы моделируете эквивалент отношения «один ко многим» в документе.

  • Вы просто используете массивы, где каждый элемент в массиве может быть простым значением или другим сложным объектом, даже другим массивом.

  • Таким образом, в одной семье может быть несколько родителей и несколько детей, и если вы посмотрите на дочерние объекты, у них есть свойство питомца, которое само по себе является вложенным массивом для отношений один-много между детьми и домашними животными.

  • Для свойства location мы объединяем три связанных свойства: штат, округ и город в объект.

  • Встраивание объекта таким способом, а не встраивание массива объектов, аналогично взаимно-однозначному отношению между двумя строками в отдельных таблицах в реляционной базе данных.

Например, свойство parent предоставляется в виде массива JSON, обозначенного квадратными скобками.

У нас также есть другой массив для дочерних элементов, хотя в этом примере есть только один дочерний массив. Вот как вы моделируете эквивалент отношения «один ко многим» в документе.

Вы просто используете массивы, где каждый элемент в массиве может быть простым значением или другим сложным объектом, даже другим массивом.

Таким образом, в одной семье может быть несколько родителей и несколько детей, и если вы посмотрите на дочерние объекты, у них есть свойство питомца, которое само по себе является вложенным массивом для отношений один-много между детьми и домашними животными.

Для свойства location мы объединяем три связанных свойства: штат, округ и город в объект.

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

Встраивание данных

Когда вы начнете моделировать данные в хранилище документов, например DocumentDB, попытайтесь обработать свои сущности как автономные документы, представленные в JSON. При работе с реляционными базами данных мы всегда нормализуем данные.

  • Для нормализации ваших данных обычно требуется взять объект, например клиента, и разбить его на отдельные части данных, такие как контактные данные и адреса.

  • Чтобы прочитать клиента со всеми его контактными данными и адресами, вам нужно использовать JOINS для эффективной агрегации ваших данных во время выполнения.

Для нормализации ваших данных обычно требуется взять объект, например клиента, и разбить его на отдельные части данных, такие как контактные данные и адреса.

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

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

{
   "id": "1", 
   "firstName": "Mark", 
   "lastName": "Upston", 
	
   "addresses": [ 
      {             
         "line1": "232 Main Street", 
         "line2": "Unit 1", 
         "city": "Brooklyn", 
         "state": "NY", 
         "zip": 11229
      }
   ],
	
   "contactDetails": [ 
      {"email": "mark.upston@xyz.com"}, 
      {"phone": "+1 356 545-86455", "extension": 5555} 
   ]
} 

Как видите, мы денормализовали запись клиента, где вся информация о клиенте встроена в один документ JSON.

В NoSQL у нас есть бесплатная схема, поэтому вы можете добавлять контактные данные и адреса в другом формате. В NoSQL вы можете извлечь запись клиента из базы данных за одну операцию чтения. Точно так же обновление записи также является единственной операцией записи.

Ниже приведены шаги по созданию документов с использованием .Net SDK.

Шаг 1 — Создание DocumentClient. Затем мы будем запрашивать базу данных myfirstdb, а также запрашивать коллекцию MyCollection, которую мы храним в этой коллекции частных переменных, чтобы она была доступна для всего класса.

private static async Task CreateDocumentClient() { 
   // Create a new instance of the DocumentClient
	
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) { 
      database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
         'myfirstdb'").AsEnumerable().First(); 
			
      collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
         "SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();  
			
      await CreateDocuments(client); 
   }

}

Шаг 2 — Создайте несколько документов в задаче CreateDocuments.

private async static Task CreateDocuments(DocumentClient client) {
   Console.WriteLine(); 
   Console.WriteLine("**** Create Documents ****"); 
   Console.WriteLine();
	
   dynamic document1Definition = new {
      name = "New Customer 1", address = new { 
         addressType = "Main Office", 
         addressLine1 = "123 Main Street", 
         location = new { 
            city = "Brooklyn", stateProvinceName = "New York"
         }, 
         postalCode = "11229", countryRegionName = "United States" 
      }, 
   };
	
   Document document1 = await CreateDocument(client, document1Definition); 
   Console.WriteLine("Created document {0} from dynamic object", document1.Id); 
   Console.WriteLine(); 
}

Первый документ будет создан из этого динамического объекта. Это может выглядеть как JSON, но, конечно, это не так. Это код C #, и мы создаем настоящий объект .NET, но нет определения класса. Вместо этого свойства выводятся из способа инициализации объекта. Вы также можете заметить, что мы не предоставили свойство Id для этого документа.

Шаг 3 — Теперь давайте посмотрим на CreateDocument, и он выглядит так же, как мы видели при создании баз данных и коллекций.

private async static Task<Document> CreateDocument(DocumentClient client,
   object documentObject) {
   var result = await client.CreateDocumentAsync(collection.SelfLink, documentObject); 
	
   var document = result.Resource; 
   Console.WriteLine("Created new document: {0}\r\n{1}", document.Id, document); 
	
   return result; 
}

Шаг 4 — На этот раз мы вызываем CreateDocumentAsync, указывая SelfLink коллекции, в которую мы хотим добавить документ. Мы получаем ответ со свойством ресурса, которое в данном случае представляет новый документ с его сгенерированными системой свойствами.

В следующей задаче CreateDocuments мы создали три документа.

  • В первом документе объект Document — это определенный класс в SDK, который наследуется от ресурса и поэтому имеет все общие свойства ресурса, но также включает динамические свойства, которые определяют сам документ без схемы.

В первом документе объект Document — это определенный класс в SDK, который наследуется от ресурса и поэтому имеет все общие свойства ресурса, но также включает динамические свойства, которые определяют сам документ без схемы.

private async static Task CreateDocuments(DocumentClient client) {
   Console.WriteLine(); 
   Console.WriteLine("**** Create Documents ****"); 
   Console.WriteLine();
	
   dynamic document1Definition = new {
      name = "New Customer 1", address = new {
         addressType = "Main Office", 
         addressLine1 = "123 Main Street", 
         location = new {
            city = "Brooklyn", stateProvinceName = "New York" 
         }, 
         postalCode = "11229", 
         countryRegionName = "United States" 
      }, 
   };
	
   Document document1 = await CreateDocument(client, document1Definition); 
   Console.WriteLine("Created document {0} from dynamic object", document1.Id); 
   Console.WriteLine();
	
   var document2Definition = @" {
      ""name"": ""New Customer 2"", 
		
      ""address"": { 
         ""addressType"": ""Main Office"", 
         ""addressLine1"": ""123 Main Street"", 
         ""location"": { 
            ""city"": ""Brooklyn"", ""stateProvinceName"": ""New York"" 
         }, 
         ""postalCode"": ""11229"", 
         ""countryRegionName"": ""United States"" 
      } 
   }"; 
	
   Document document2 = await CreateDocument(client, document2Definition); 
   Console.WriteLine("Created document {0} from JSON string", document2.Id);
   Console.WriteLine();
	
   var document3Definition = new Customer {
      Name = "New Customer 3", 
		
      Address = new Address {
         AddressType = "Main Office", 
         AddressLine1 = "123 Main Street", 
         Location = new Location {
            City = "Brooklyn", StateProvinceName = "New York" 
         }, 
         PostalCode = "11229", 
         CountryRegionName = "United States" 
      }, 
   };
	
   Document document3 = await CreateDocument(client, document3Definition); 
   Console.WriteLine("Created document {0} from typed object", document3.Id); 
   Console.WriteLine(); 
}
  • Этот второй документ работает только с необработанной строкой JSON. Теперь мы вступаем в перегрузку для CreateDocument, который использует JavaScriptSerializer для десериализации строки в объект, который затем передается тому же методу CreateDocument, который мы использовали для создания первого документа.

  • В третьем документе мы использовали объект C # Customer, который определен в нашем приложении.

Этот второй документ работает только с необработанной строкой JSON. Теперь мы вступаем в перегрузку для CreateDocument, который использует JavaScriptSerializer для десериализации строки в объект, который затем передается тому же методу CreateDocument, который мы использовали для создания первого документа.

В третьем документе мы использовали объект C # Customer, который определен в нашем приложении.

Давайте посмотрим на этого клиента, у него есть свойство Id и address, где адрес — это вложенный объект со своими собственными свойствами, включая location, который является еще одним вложенным объектом.

using Newtonsoft.Json; 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks;

namespace DocumentDBDemo {
 
   public class Customer { 
      [JsonProperty(PropertyName = "id")] 
      public string Id { get; set; }
      // Must be nullable, unless generating unique values for new customers on client  
      [JsonProperty(PropertyName = "name")] 
      public string Name { get; set; }  
      [JsonProperty(PropertyName = "address")] 
      public Address Address { get; set; } 
   }
	
   public class Address {
      [JsonProperty(PropertyName = "addressType")] 
      public string AddressType { get; set; }  
		
      [JsonProperty(PropertyName = "addressLine1")] 
      public string AddressLine1 { get; set; }  
		
      [JsonProperty(PropertyName = "location")] 
      public Location Location { get; set; }  
		
      [JsonProperty(PropertyName = "postalCode")] 
      public string PostalCode { get; set; }  
		
      [JsonProperty(PropertyName = "countryRegionName")] 
      public string CountryRegionName { get; set; } 
   }
	
   public class Location { 
      [JsonProperty(PropertyName = "city")] 
      public string City { get; set; }  
		
      [JsonProperty(PropertyName = "stateProvinceName")]
      public string StateProvinceName { get; set; } 
   } 
}

У нас также есть атрибуты свойств JSON, потому что мы хотим поддерживать надлежащие соглашения по обе стороны границы.

Поэтому я просто создаю свой объект New Customer вместе с вложенными дочерними объектами и снова вызываю CreateDocument. Хотя у нашего объекта customer есть свойство Id, мы не указали его значение, поэтому DocumentDB сгенерировал его на основе GUID, как и в предыдущих двух документах.

Когда приведенный выше код скомпилирован и выполнен, вы получите следующий вывод.

**** Create Documents ****  
Created new document: 575882f0-236c-4c3d-81b9-d27780206b2c 
{ 
  "name": "New Customer 1", 
  "address": { 
    "addressType": "Main Office", 
    "addressLine1": "123 Main Street", 
    "location": { 
      "city": "Brooklyn", 
      "stateProvinceName": "New York" 
    }, 
    "postalCode": "11229", 
    "countryRegionName": "United States" 
  }, 
  "id": "575882f0-236c-4c3d-81b9-d27780206b2c", 
  "_rid": "kV5oANVXnwDGPgAAAAAAAA==", 
  "_ts": 1450037545, 
  "_self": "dbs/kV5oAA==/colls/kV5oANVXnwA=/docs/kV5oANVXnwDGPgAAAAAAAA==/", 
  "_etag": "\"00006fce-0000-0000-0000-566dd1290000\"", 
  "_attachments": "attachments/" 
} 
Created document 575882f0-236c-4c3d-81b9-d27780206b2c from dynamic object  
Created new document: 8d7ad239-2148-4fab-901b-17a85d331056 
{ 
  "name": "New Customer 2", 
  "address": {
    "addressType": "Main Office", 
    "addressLine1": "123 Main Street", 
    "location": { 
      "city": "Brooklyn", 
      "stateProvinceName": "New York" 
    }, 
    "postalCode": "11229", 
    "countryRegionName": "United States" 
  }, 
  "id": "8d7ad239-2148-4fab-901b-17a85d331056", 
  "_rid": "kV5oANVXnwDHPgAAAAAAAA==", 
  "_ts": 1450037545, 
  "_self": "dbs/kV5oAA==/colls/kV5oANVXnwA=/docs/kV5oANVXnwDHPgAAAAAAAA==/", 
  "_etag": "\"000070ce-0000-0000-0000-566dd1290000\"", 
  "_attachments": "attachments/" 
} 
Created document 8d7ad239-2148-4fab-901b-17a85d331056 from JSON string  
Created new document: 49f399a8-80c9-4844-ac28-cd1dee689968 
{ 
  "id": "49f399a8-80c9-4844-ac28-cd1dee689968", 
  "name": "New Customer 3", 
  "address": { 
    "addressType": "Main Office", 
    "addressLine1": "123 Main Street", 
    "location": { 
      "city": "Brooklyn", 
      "stateProvinceName": "New York" 
    }, 
    "postalCode": "11229", 
    "countryRegionName": "United States" 
  }, 
  "_rid": "kV5oANVXnwDIPgAAAAAAAA==", 
  "_ts": 1450037546, 
  "_self": "dbs/kV5oAA==/colls/kV5oANVXnwA=/docs/kV5oANVXnwDIPgAAAAAAAA==/", 
  "_etag": "\"000071ce-0000-0000-0000-566dd12a0000\"", 
  "_attachments": "attachments/" 
}
Created document 49f399a8-80c9-4844-ac28-cd1dee689968 from typed object

DocumentDB — типы данных

Обозначение объектов JSON или JavaScript — это легкий текстовый открытый стандарт, разработанный для удобочитаемого обмена данными, а также простой для машин для анализа и генерации. JSON лежит в основе DocumentDB. Мы передаем JSON по проводам, сохраняем JSON как JSON и индексируем дерево JSON, разрешая запросы к полному документу JSON.

Формат JSON поддерживает следующие типы данных —

S.No. Тип и описание
1

Число

Формат с плавающей точкой двойной точности в JavaScript

2

строка

Unicode с двойными кавычками с обратной косой чертой

3

логический

Правда или ложь

4

массив

Упорядоченная последовательность значений

5

Значение

Это может быть строка, число, истина или ложь, ноль и т. Д.

6

объект

Неупорядоченный набор пар ключ: значение

7

Пробелы

Может использоваться между любой парой токенов

8

Ноль

пустой

Число

Формат с плавающей точкой двойной точности в JavaScript

строка

Unicode с двойными кавычками с обратной косой чертой

логический

Правда или ложь

массив

Упорядоченная последовательность значений

Значение

Это может быть строка, число, истина или ложь, ноль и т. Д.

объект

Неупорядоченный набор пар ключ: значение

Пробелы

Может использоваться между любой парой токенов

Ноль

пустой

Давайте рассмотрим простой пример типа DateTime. Добавьте дату рождения в класс клиента.

public class Customer {
   [JsonProperty(PropertyName = "id")] 
   public string Id { get; set; }
	
   // Must be nullable, unless generating unique values for new customers on client  
   [JsonProperty(PropertyName = "name")] 
   public string Name { get; set; }  
	
   [JsonProperty(PropertyName = "address")] 
   public Address Address { get; set; }  
	
   [JsonProperty(PropertyName = "birthDate")] 
   public DateTime BirthDate { get; set; } 
}

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

private async static Task CreateDocuments(DocumentClient client) {
   Console.WriteLine(); 
   Console.WriteLine("**** Create Documents ****"); 
   Console.WriteLine();
	
   var document3Definition = new Customer { 
      Id = "1001", 
      Name = "Luke Andrew", 
		
      Address = new Address { 
         AddressType = "Main Office", 
         AddressLine1 = "123 Main Street", 
         Location = new Location {
            City = "Brooklyn",
            StateProvinceName = "New York" 
         }, 
         PostalCode = "11229",
         CountryRegionName = "United States" 
      },
		
      BirthDate = DateTime.Parse(DateTime.Today.ToString()), 
   };
	
   Document document3 = await CreateDocument(client, document3Definition); 
   Console.WriteLine("Created document {0} from typed object", document3.Id); 
   Console.WriteLine(); 
}

Когда приведенный выше код скомпилирован и выполнен, а документ создан, вы увидите, что дата рождения добавлена.

**** Create Documents ****  
Created new document: 1001 
{ 
   "id": "1001", 
   "name": "Luke Andrew", 
   "address": { 
      "addressType": "Main Office", 
      "addressLine1": "123 Main Street", 
      "location": { 
         "city": "Brooklyn", 
         "stateProvinceName": "New York" 
      }, 
      "postalCode": "11229", 
      "countryRegionName": "United States" 
   }, 
   "birthDate": "2015-12-14T00:00:00", 
   "_rid": "Ic8LAMEUVgAKAAAAAAAAAA==", 
   "_ts": 1450113676, 
   "_self": "dbs/Ic8LAA==/colls/Ic8LAMEUVgA=/docs/Ic8LAMEUVgAKAAAAAAAAAA==/", 
   "_etag": "\"00002d00-0000-0000-0000-566efa8c0000\"", 
   "_attachments": "attachments/" 
} 
Created document 1001 from typed object

DocumentDB — Ограничение записей

Недавно корпорация Майкрософт добавила ряд улучшений в способе выполнения запросов к Azure DocumentDB, таких как ключевое слово TOP к грамматике SQL, которое ускорило выполнение запросов и потребляет меньше ресурсов, увеличило ограничения для операторов запросов и добавило поддержку дополнительных операторов LINQ в. .NET SDK.

Давайте рассмотрим простой пример, в котором мы получим только первые две записи. Если у вас есть несколько записей и вы хотите получить только некоторые из них, вы можете использовать ключевое слово Top. В этом примере у нас много записей землетрясений.

Ограничение записей

Теперь мы хотим показать только первые две записи

Шаг 1 — Перейдите в проводник запросов и запустите этот запрос.

SELECT * FROM c 
WHERE c.magnitude > 2.5 

Вы увидите, что он получил четыре записи, потому что мы еще не указали ключевое слово TOP.

Восстановленные записи

Шаг 2 — Теперь используйте ключевое слово TOP с тем же запросом. Здесь мы указали ключевое слово TOP, а ‘2’ означает, что нам нужны только две записи.

SELECT TOP 2 * FROM c 
WHERE c.magnitude > 2.5

Шаг 3 — Теперь запустите этот запрос, и вы увидите, что извлекаются только две записи.

Две записи получены

Точно так же вы можете использовать ключевое слово TOP в коде, используя .Net SDK. Ниже приводится реализация.

private async static Task QueryDocumentsWithPaging(DocumentClient client) {
   Console.WriteLine(); 
   Console.WriteLine("**** Query Documents (paged results) ****"); 
   Console.WriteLine();  
   Console.WriteLine("Quering for all documents"); 
	
   var sql = "SELECT TOP 3 * FROM c";  
   var query = client 
      .CreateDocumentQuery(collection.SelfLink, sql) 
      .AsDocumentQuery(); 
		
   while (query.HasMoreResults) {
      var documents = await query.ExecuteNextAsync(); 
		
      foreach (var document in documents) { 
         Console.WriteLine(" PublicId: {0}; Magnitude: {1};", document.publicid,
            document.magnitude); 
      } 
   } 
	
   Console.WriteLine(); 
}

Ниже приводится задача CreateDocumentClient, в которой создаются экземпляры базы данных DocumentClient и землетрясения.

private static async Task CreateDocumentClient() {
   // Create a new instance of the DocumentClient 
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
      database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
         'earthquake'").AsEnumerable().First(); 
			
      collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
         "SELECT * FROM c WHERE c.id = 'earthquakedata'").AsEnumerable().First(); 
			
      await QueryDocumentsWithPaging(client); 
   } 
}

Когда приведенный выше код скомпилирован и выполнен, вы увидите, что извлекаются только три записи.

**** Query Documents (paged results) **** 
 
Quering for all documents 
PublicId: 2015p947400; Magnitude: 2.515176918; 
PublicId: 2015p947373; Magnitude: 1.506774108; 
PublicId: 2015p947329; Magnitude: 1.593394461;

DocumentDB — сортировка записей

Microsoft Azure DocumentDB поддерживает запросы документов с использованием документов SQL поверх JSON. Вы можете сортировать документы в коллекции по номерам и строкам, используя в запросе предложение ORDER BY. Предложение может включать необязательный аргумент ASC / DESC для указания порядка, в котором должны быть получены результаты.

Давайте посмотрим на следующий пример, в котором у нас есть документ JSON.

{ 
   "id": "Food Menu",
   "description": "Grapes, red or green (European type, such as Thompson seedless), raw",
	
   "tags": [
      {
         "name": "grapes"
      },
		
      {
         "name": "red or green (european type"
      },
		
      {
         "name": "such as thompson seedless)"
      },
		
      {
         "name": "raw"
      }
   ],
	
   "foodGroup": "Fruits and Fruit Juices",
	
   "servings": [
      {
         "amount": 1,
         "description": "cup",
         "weightInGrams": 151
      },
		
      {
         "amount": 10,
         "description": "grapes",
         "weightInGrams": 49
      },
		
      {
         "amount": 1,
         "description": "NLEA serving",
         "weightInGrams": 126
      }
   ]
	
}

Ниже приведен SQL-запрос для сортировки результата в порядке убывания.

SELECT f.description, f.foodGroup,  
   f.servings[2].description AS servingDescription,  
   f.servings[2].weightInGrams AS servingWeight  
	
FROM f  
ORDER BY f.servings[2].weightInGrams DESC 

Когда вышеуказанный запрос будет выполнен, вы получите следующий вывод.

[
   {
      "description": "Grapes, red or green (European type, such as Thompson
         seedless), raw",
      "foodGroup": "Fruits and Fruit Juices",
      "servingDescription": "NLEA serving",
      "servingWeight": 126
   }
]

DocumentDB — индексирование записей

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

Политика индексации по умолчанию, которая указывает DocumentDB автоматически индексировать каждое свойство, подходит для многих распространенных сценариев. Но вы также можете реализовать собственную политику, которая точно контролирует, что именно индексируется, а что нет, и другие функции в отношении индексации.

DocumentDB поддерживает следующие типы индексации —

  • гашиш
  • Спектр

гашиш

Индекс хэша позволяет эффективно запрашивать равенство, т. Е. При поиске документов, в которых заданное свойство равно точному значению, а не при сопоставлении с диапазоном значений, таких как меньше, больше или между.

Вы можете выполнять запросы диапазона с хэш-индексом, но DocumentDB не сможет использовать хэш-индекс для поиска подходящих документов, и вместо этого ему придется последовательно сканировать каждый документ, чтобы определить, должен ли он быть выбран с помощью запроса диапазона.

Вы не сможете отсортировать документы с помощью предложения ORDER BY для свойства, имеющего только хэш-индекс.

Спектр

Индекс диапазона, определенный для свойства DocumentDB, позволяет эффективно запрашивать документы по диапазону значений. Это также позволяет вам сортировать результаты запроса по этому свойству, используя ORDER BY.

DocumentDB позволяет вам определять как хэш, так и индекс диапазона для любого или всех свойств, что позволяет эффективно выполнять запросы на равенство и диапазон, а также ORDER BY.

Политика индексации

Каждая коллекция имеет политику индексации, которая определяет, какие типы индексов используются для чисел и строк в каждом свойстве каждого документа.

  • Вы также можете контролировать, будут ли документы проиндексированы автоматически при их добавлении в коллекцию.

  • Автоматическое индексирование включено по умолчанию, но вы можете изменить это поведение при добавлении документа, сказав DocumentDB не индексировать этот конкретный документ.

  • Вы можете отключить автоматическую индексацию, чтобы по умолчанию документы не индексировались при добавлении в коллекцию. Точно так же вы можете переопределить это на уровне документа и дать указание DocumentDB индексировать конкретный документ при добавлении его в коллекцию. Это известно как ручное индексирование.

Вы также можете контролировать, будут ли документы проиндексированы автоматически при их добавлении в коллекцию.

Автоматическое индексирование включено по умолчанию, но вы можете изменить это поведение при добавлении документа, сказав DocumentDB не индексировать этот конкретный документ.

Вы можете отключить автоматическую индексацию, чтобы по умолчанию документы не индексировались при добавлении в коллекцию. Точно так же вы можете переопределить это на уровне документа и дать указание DocumentDB индексировать конкретный документ при добавлении его в коллекцию. Это известно как ручное индексирование.

Включить / исключить индексирование

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

В этих случаях вы можете уменьшить накладные расходы на индексирование, сказав DocumentDB индексировать только те конкретные части каждого документа, добавленные в коллекцию.

Автоматическая индексация

Давайте рассмотрим простой пример автоматической индексации.

Шаг 1. Сначала мы создаем коллекцию с именем autoindexing, и без явного указания политики эта коллекция использует политику индексации по умолчанию, что означает, что для этой коллекции включена автоматическая индексация.

Здесь мы используем маршрутизацию на основе идентификатора для самоопределения базы данных, поэтому нам не нужно знать его идентификатор ресурса или запрашивать его перед созданием коллекции. Мы можем просто использовать идентификатор базы данных, который является mydb.

Шаг 2 — Теперь давайте создадим два документа, оба с фамилией Upston.

private async static Task AutomaticIndexing(DocumentClient client) {
   Console.WriteLine();
   Console.WriteLine("**** Override Automatic Indexing ****");

   // Create collection with automatic indexing

   var collectionDefinition = new DocumentCollection {
      Id = "autoindexing"
   };
	
   var collection = await client.CreateDocumentCollectionAsync("dbs/mydb",
      collectionDefinition);

   // Add a document (indexed)
   dynamic indexedDocumentDefinition = new {
      id = "MARK",
      firstName = "Mark",
      lastName = "Upston",
      addressLine = "123 Main Street",
      city = "Brooklyn",
      state = "New York",
      zip = "11229",
   };
	
   Document indexedDocument = await client
      .CreateDocumentAsync("dbs/mydb/colls/autoindexing", indexedDocumentDefinition);
		
   // Add another document (request no indexing)
   dynamic unindexedDocumentDefinition = new {
      id = "JANE",
      firstName = "Jane",
      lastName = "Upston",
      addressLine = "123 Main Street",
      city = "Brooklyn",
      state = "New York",
      zip = "11229",
   };
	
   Document unindexedDocument = await client
      .CreateDocumentAsync("dbs/mydb/colls/autoindexing", unindexedDocumentDefinition,
      new RequestOptions { IndexingDirective = IndexingDirective.Exclude });

   //Unindexed document won't get returned when querying on non-ID (or selflink) property

   var doeDocs = client.CreateDocumentQuery("dbs/mydb/colls/autoindexing", "SELECT *
      FROM c WHERE c.lastName = 'Doe'").ToList();
		
   Console.WriteLine("Documents WHERE lastName = 'Doe': {0}", doeDocs.Count);

   // Unindexed document will get returned when using no WHERE clause

   var allDocs = client.CreateDocumentQuery("dbs/mydb/colls/autoindexing",
      "SELECT * FROM c").ToList();
   Console.WriteLine("All documents: {0}", allDocs.Count);
	
   // Unindexed document will get returned when querying by ID (or self-link) property
	
   Document janeDoc = client.CreateDocumentQuery("dbs/mydb/colls/autoindexing",
      "SELECT * FROM c WHERE c.id = 'JANE'").AsEnumerable().FirstOrDefault();
   Console.WriteLine("Unindexed document self-link: {0}", janeDoc.SelfLink);
	
   // Delete the collection
	
   await client.DeleteDocumentCollectionAsync("dbs/mydb/colls/autoindexing");
}

Этот первый, для Марка Апстона, добавляется в коллекцию, а затем сразу же индексируется автоматически на основе политики индексации по умолчанию.

Но когда был добавлен второй документ для Марка Апстона, мы передали параметры запроса с помощью IndexingDirective.Exclude, которое явно указывает DocumentDB не индексировать этот документ, несмотря на политику индексации коллекции.

У нас есть разные типы запросов для обоих документов в конце.

Шаг 3 — Давайте вызовем задачу AutomaticIndexing из CreateDocumentClient.

private static async Task CreateDocumentClient() {
   // Create a new instance of the DocumentClient 
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) { 
      await AutomaticIndexing(client); 
   } 
}

Когда приведенный выше код скомпилирован и выполнен, вы получите следующий вывод.

**** Override Automatic Indexing **** 
Documents WHERE lastName = 'Upston': 1 
All documents: 2 
Unindexed document self-link: dbs/kV5oAA==/colls/kV5oAOEkfQA=/docs/kV5oAOEkfQACA 
AAAAAAAAA==/

Как видите, у нас есть два таких документа, но запрос возвращает только один для Марка, потому что один для Марка не проиндексирован. Если мы запросим снова, без предложения WHERE, чтобы получить все документы в коллекции, то мы получим набор результатов с обоими документами, и это потому, что неиндексированные документы всегда возвращаются запросами, у которых нет предложения WHERE.

Мы также можем получить неиндексированные документы по их идентификатору или по собственной ссылке. Поэтому, когда мы запрашиваем документ Марка по его идентификатору, MARK, мы видим, что DocumentDB возвращает документ, даже если он не проиндексирован в коллекции.

Ручное индексирование

Давайте посмотрим на простой пример ручной индексации путем переопределения автоматической индексации.

Шаг 1 — Сначала мы создадим коллекцию под названием manualindexing и переопределим политику по умолчанию, явно отключив автоматическую индексацию. Это означает, что, если мы не потребуем иного, новые документы, добавленные в эту коллекцию, не будут проиндексированы.

private async static Task ManualIndexing(DocumentClient client) {
   Console.WriteLine();
   Console.WriteLine("**** Manual Indexing ****");
   // Create collection with manual indexing

   var collectionDefinition = new DocumentCollection {
      Id = "manualindexing",
      IndexingPolicy = new IndexingPolicy {
         Automatic = false,
      },
   };
	
   var collection = await client.CreateDocumentCollectionAsync("dbs/mydb",
      collectionDefinition);
		
   // Add a document (unindexed)
   dynamic unindexedDocumentDefinition = new {
      id = "MARK",
      firstName = "Mark",
      lastName = "Doe",
      addressLine = "123 Main Street",
      city = "Brooklyn",
      state = "New York",
      zip = "11229",
   }; 
	
   Document unindexedDocument = await client
      .CreateDocumentAsync("dbs/mydb/colls/manualindexing", unindexedDocumentDefinition);
  
   // Add another document (request indexing)
   dynamic indexedDocumentDefinition = new {
      id = "JANE",
      firstName = "Jane",
      lastName = "Doe",
      addressLine = "123 Main Street",
      city = "Brooklyn",
      state = "New York",
      zip = "11229",
   };
	
   Document indexedDocument = await client.CreateDocumentAsync
      ("dbs/mydb/colls/manualindexing", indexedDocumentDefinition, new RequestOptions {
      IndexingDirective = IndexingDirective.Include });

   //Unindexed document won't get returned when querying on non-ID (or selflink) property

   var doeDocs = client.CreateDocumentQuery("dbs/mydb/colls/manualindexing",
      "SELECT * FROM c WHERE c.lastName = 'Doe'").ToList();
   Console.WriteLine("Documents WHERE lastName = 'Doe': {0}", doeDocs.Count);
	
   // Unindexed document will get returned when using no WHERE clause
	
   var allDocs = client.CreateDocumentQuery("dbs/mydb/colls/manualindexing",
      "SELECT * FROM c").ToList();
   Console.WriteLine("All documents: {0}", allDocs.Count);
	
   // Unindexed document will get returned when querying by ID (or self-link) property
	
   Document markDoc = client
      .CreateDocumentQuery("dbs/mydb/colls/manualindexing",
      "SELECT * FROM c WHERE c.id = 'MARK'")
      .AsEnumerable().FirstOrDefault();
   Console.WriteLine("Unindexed document self-link: {0}", markDoc.SelfLink);
   await client.DeleteDocumentCollectionAsync("dbs/mydb/colls/manualindexing");
}

Шаг 2 — Теперь мы снова создадим те же два документа, что и раньше. На этот раз мы не будем предоставлять никаких специальных параметров запроса для документа Марка, поскольку из-за политики индексирования коллекции этот документ не будет проиндексирован.

Шаг 3 — Теперь, когда мы добавляем второй документ для Mark, мы используем RequestOptions с IndexingDirective.Include, чтобы сообщить DocumentDB, что он должен индексировать этот документ, который переопределяет политику индексации коллекции, которая говорит, что это не должно.

У нас есть разные типы запросов для обоих документов в конце.

Шаг 4 — Давайте вызовем задачу ManualIndexing из CreateDocumentClient.

private static async Task CreateDocumentClient() {
   // Create a new instance of the DocumentClient 
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
      await ManualIndexing(client); 
   } 
}

Когда приведенный выше код скомпилирован и выполнен, вы получите следующий вывод.

**** Manual Indexing **** 
Documents WHERE lastName = 'Upston': 1 
All documents: 2 
Unindexed document self-link: dbs/kV5oAA==/colls/kV5oANHJPgE=/docs/kV5oANHJPgEBA 
AAAAAAAAA==/

Опять же, запрос возвращает только один из двух документов, но на этот раз он возвращает Джейн Доу, которую мы явно просили проиндексировать. Но опять же, как и раньше, запрос без предложения WHERE возвращает все документы в коллекции, включая неиндексированный документ для Марка. Мы также можем запросить неиндексированный документ по его идентификатору, который возвращает DocumentDB, даже если он не проиндексирован.

DocumentDB — геопространственные данные

Microsoft добавила геопространственную поддержку , которая позволяет хранить данные о местоположении в ваших документах и ​​выполнять пространственные вычисления для расстояния и пересечений между точками и полигонами.

  • Пространственные данные описывают положение и форму объектов в пространстве.

  • Как правило, его можно использовать для представления местоположения человека, интересующей его достопримечательности, границы города или озера.

  • Обычные случаи использования часто включают запросы о близости. Например, «найти все университеты рядом с моим текущим местоположением».

Пространственные данные описывают положение и форму объектов в пространстве.

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

Обычные случаи использования часто включают запросы о близости. Например, «найти все университеты рядом с моим текущим местоположением».

Точка обозначает одну позицию в пространстве, которая представляет точное местоположение, например, адрес улицы конкретного университета. Точка представлена ​​в DocumentDB с использованием ее пары координат (долгота и широта). Ниже приведен пример точки JSON.

{ 
   "type":"Point", 
   "coordinates":[ 28.3, -10.7 ] 
} 

Давайте посмотрим на простой пример, который содержит местонахождение университета.

{ 
   "id":"case-university", 
   "name":"CASE: Center For Advanced Studies In Engineering", 
   "city":"Islamabad", 
	
   "location": { 
      "type":"Point", 
      "coordinates":[ 33.7194136, -73.0964862 ] 
   } 
}

Чтобы получить название университета на основе местоположения, вы можете использовать следующий запрос.

SELECT c.name FROM c 

WHERE c.id = "case-university" AND ST_ISVALID({ 
      "type":"Point", 
      "coordinates":[ 33.7194136, -73.0964862 ]})

Когда вышеуказанный запрос будет выполнен, вы получите следующий вывод.

[ 
   { 
      "name": "CASE: Center For Advanced Studies In Engineering" 
   } 
] 

Создать документ с геопространственными данными в .NET

Вы можете создать документ с геопространственными данными, давайте рассмотрим простой пример, в котором создается университетский документ.

private async static Task CreateDocuments(DocumentClient client) {
   Console.WriteLine(); 
   Console.WriteLine("**** Create Documents ****"); 
   Console.WriteLine();
	
   var uniDocument = new UniversityProfile {
      Id = "nust", 
      Name = "National University of Sciences and Technology", 
      City = "Islamabad", 
      Loc = new Point(33.6455715, 72.9903447) 
   };
	
   Document document = await CreateDocument(client, uniDocument); 
   Console.WriteLine("Created document {0} from typed object", document.Id); 
   Console.WriteLine(); 
}

Ниже приведена реализация для класса UniversityProfile.

public class UniversityProfile { 
   [JsonProperty(PropertyName = "id")] 
   public string Id { get; set; }  
	
   [JsonProperty("name")] 
   public string Name { get; set; }
	
   [JsonProperty("city")] 
   public string City { get; set; }  
	
   [JsonProperty("location")] 
   public Point Loc { get; set; } 
} 

Когда приведенный выше код скомпилирован и выполнен, вы получите следующий вывод.

**** Create Documents ****  
Created new document: nust 
{ 
   "id": "nust", 
   "name": "National University of Sciences and Technology", 
   "city": "Islamabad", 
   "location": { 
      "type": "Point", 
      "coordinates": [ 
         33.6455715, 
         72.9903447 
      ] 
   }, 
   "_rid": "Ic8LAMEUVgANAAAAAAAAAA==", 
   "_ts": 1450200910, 
   "_self": "dbs/Ic8LAA==/colls/Ic8LAMEUVgA=/docs/Ic8LAMEUVgANAAAAAAAAAA==/", 
   "_etag": "\"00004100-0000-0000-0000-56704f4e0000\"", 
   "_attachments": "attachments/" 
} 
Created document nust from typed object 

DocumentDB — Разделение

Когда размер вашей базы данных начинает превышать 10 ГБ, вы можете просто расширять ее, создавая новые коллекции, а затем распределяя или разбивая свои данные на все больше и больше коллекций.

Рано или поздно одной коллекции, имеющей емкость 10 ГБ, будет недостаточно для размещения вашей базы данных. Теперь 10 ГБ может показаться не очень большим числом, но помните, что мы храним документы JSON, которые представляют собой просто текст, и вы можете разместить много простых текстовых документов в 10 ГБ, даже если учесть затраты на хранение для индексов.

Хранение не единственная проблема, когда речь заходит о масштабируемости. Максимальная пропускная способность, доступная для коллекции, составляет две с половиной тысячи единиц запроса в секунду, которые вы получаете с коллекцией S3. Следовательно, если вам нужна более высокая пропускная способность, вам также нужно будет масштабировать, разбивая на несколько коллекций. Разделение по горизонтали также называется горизонтальным разделением .

Существует много подходов, которые можно использовать для разделения данных с помощью Azure DocumentDB. Ниже приведены наиболее распространенные стратегии —

  • Побочное Разделение
  • Разделение диапазона
  • Поиск разделов
  • Хеш-разделение

Побочное Разделение

Побочное разделение — самая простая стратегия, потому что нет ключа разделения. Часто это хороший выбор, если вы не уверены во многих вещах. Вы можете не знать, нужно ли вам когда-либо расширять масштаб до одной коллекции или сколько коллекций вам может понадобиться добавить, или как быстро вам может понадобиться добавить их.

  • Побочное разделение начинается с одной коллекции и ключа раздела не существует.

  • Коллекция начинает расти, а затем увеличивается еще немного, а затем еще больше, пока вы не начнете приближаться к пределу в 10 ГБ.

  • Когда вы достигаете 90-процентной емкости, вы перетекаете в новую коллекцию и начинаете использовать ее для новых документов.

  • Как только ваша база данных масштабируется до большего количества коллекций, вы, вероятно, захотите перейти к стратегии, основанной на ключе раздела.

  • Когда вы сделаете это, вам нужно будет перебалансировать данные, переместив документы в разные коллекции в зависимости от выбранной вами стратегии.

Побочное разделение начинается с одной коллекции и ключа раздела не существует.

Коллекция начинает расти, а затем увеличивается еще немного, а затем еще больше, пока вы не начнете приближаться к пределу в 10 ГБ.

Когда вы достигаете 90-процентной емкости, вы перетекаете в новую коллекцию и начинаете использовать ее для новых документов.

Как только ваша база данных масштабируется до большего количества коллекций, вы, вероятно, захотите перейти к стратегии, основанной на ключе раздела.

Когда вы сделаете это, вам нужно будет перебалансировать данные, переместив документы в разные коллекции в зависимости от выбранной вами стратегии.

Разделение диапазона

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

  • Даты очень часто используются в этой стратегии, когда вы создаете коллекцию для хранения документов, попадающих в определенный диапазон дат. Когда вы определяете диапазоны, которые достаточно малы, вы уверены, что ни одна коллекция не превысит свой предел в 10 ГБ. Например, может быть сценарий, когда одна коллекция может разумно обрабатывать документы в течение всего месяца.

  • Также может быть так, что большинство пользователей запрашивают текущие данные, которые будут данными за этот месяц или, возможно, за последний месяц, но пользователи редко ищут более старые данные. Итак, вы начинаете в июне с коллекции S3, которая является самой дорогой коллекцией, которую вы можете купить, и обеспечивает наилучшую пропускную способность, которую вы можете получить.

  • В июле вы покупаете другую коллекцию S3 для хранения данных за июль, а также масштабируете июньские данные до менее дорогой коллекции S2. Затем в августе вы получаете еще одну коллекцию S3 и масштабируете июль до S2, а июнь — до S1. Это происходит месяц за месяцем, где вы всегда сохраняете текущие данные доступными для высокой пропускной способности, а старые данные хранятся в доступе для более низких пропускных способностей.

  • Пока запрос предоставляет ключ раздела, будет запрашиваться только коллекция, которая должна быть запрошена, а не все коллекции в базе данных, как это происходит при вторичном разделении.

Даты очень часто используются в этой стратегии, когда вы создаете коллекцию для хранения документов, попадающих в определенный диапазон дат. Когда вы определяете диапазоны, которые достаточно малы, вы уверены, что ни одна коллекция не превысит свой предел в 10 ГБ. Например, может быть сценарий, когда одна коллекция может разумно обрабатывать документы в течение всего месяца.

Также может быть так, что большинство пользователей запрашивают текущие данные, которые будут данными за этот месяц или, возможно, за последний месяц, но пользователи редко ищут более старые данные. Итак, вы начинаете в июне с коллекции S3, которая является самой дорогой коллекцией, которую вы можете купить, и обеспечивает наилучшую пропускную способность, которую вы можете получить.

В июле вы покупаете другую коллекцию S3 для хранения данных за июль, а также масштабируете июньские данные до менее дорогой коллекции S2. Затем в августе вы получаете еще одну коллекцию S3 и масштабируете июль до S2, а июнь — до S1. Это происходит месяц за месяцем, где вы всегда сохраняете текущие данные доступными для высокой пропускной способности, а старые данные хранятся в доступе для более низких пропускных способностей.

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

Поиск разделов

С помощью поиска разделов вы можете определить карту разделов, которая направляет документы в определенные коллекции на основе их ключа раздела. Например, вы можете разделить по регионам.

  • Храните все документы США в одной коллекции, все европейские документы в другой коллекции и все документы из любого другого региона в третьей коллекции.

  • Используйте эту карту разделов, и средство поиска разделов поиска может выяснить, в какой коллекции создать документ и какие коллекции запрашивать, основываясь на ключе раздела, который является свойством региона, содержащимся в каждом документе.

Храните все документы США в одной коллекции, все европейские документы в другой коллекции и все документы из любого другого региона в третьей коллекции.

Используйте эту карту разделов, и средство поиска разделов поиска может выяснить, в какой коллекции создать документ и какие коллекции запрашивать, основываясь на ключе раздела, который является свойством региона, содержащимся в каждом документе.

Хеш-разделение

В хэш-секционировании разделы назначаются на основе значения хэш-функции, что позволяет равномерно распределять запросы и данные по нескольким разделам.

Это обычно используется для разделения данных, произведенных или потребленных большим количеством различных клиентов, и полезно для хранения пользовательских профилей, элементов каталога и т. Д.

Давайте рассмотрим простой пример разделения диапазонов с использованием RangePartitionResolver, поставляемого .NET SDK.

Шаг 1 — Создайте новый DocumentClient, и мы создадим две коллекции в задаче CreateCollections. Один будет содержать документы для пользователей, которые имеют идентификаторы пользователей, начинающиеся с A до M, а другой — для идентификаторов пользователей от N до Z.

private static async Task CreateCollections(DocumentClient client) {
   await client.CreateDocumentCollectionAsync(“dbs/myfirstdb”, new DocumentCollection {
      Id = CollectionAM }); 
		
   await client.CreateDocumentCollectionAsync(“dbs/myfirstdb”, new DocumentCollection {
      Id = CollectionNZ }); 
}

Шаг 2 — Зарегистрируйте преобразователь диапазона для базы данных.

Шаг 3 — Создайте новый RangePartitionResolver <string>, который является типом данных нашего ключа раздела. Конструктор принимает два параметра: имя свойства ключа раздела и словарь, который является картой сегментов или картой разделов, которая является просто списком диапазонов и соответствующих коллекций, которые мы предварительно определяем для распознавателя.

private static void RegisterRangeResolver(DocumentClient client) {

   //Note: \uffff is the largest UTF8 value, so M\ufff includes all strings that start with M.
		
   var resolver = new RangePartitionResolver<string>(
      "userId", new Dictionary<Range<string>, string>() {
      { new Range<string>("A", "M\uffff"), "dbs/myfirstdb/colls/CollectionAM" },
      { new Range<string>("N", "Z\uffff"), "dbs/myfirstdb/colls/CollectionNZ" },
   });
	
   client.PartitionResolvers["dbs/myfirstdb"] = resolver;
 }

Здесь необходимо закодировать максимально возможное значение UTF-8. В противном случае первый диапазон не будет совпадать ни с одним M, кроме одного M, а также для Z во втором диапазоне. Таким образом, вы можете просто подумать об этом закодированном значении здесь как о подстановочном знаке для соответствия ключу раздела.

Шаг 4 — После создания распознавателя зарегистрируйте его для базы данных с текущим DocumentClient. Для этого просто присвойте его свойству словаря PartitionResolver.

Мы будем создавать и запрашивать документы в базе данных, а не в коллекции, как обычно, распознаватель будет использовать эту карту для маршрутизации запросов в соответствующие коллекции.

Теперь давайте создадим несколько документов. Сначала мы создадим один для userId Кирка, а затем один для Спока.

private static async Task CreateDocumentsAcrossPartitions(DocumentClient client) { 
   Console.WriteLine(); 
   Console.WriteLine("**** Create Documents Across Partitions ****");
	
   var kirkDocument = await client.CreateDocumentAsync("dbs/myfirstdb", new { userId =
      "Kirk", title = "Captain" }); 
   Console.WriteLine("Document 1: {0}", kirkDocument.Resource.SelfLink);
	
   var spockDocument = await client.CreateDocumentAsync("dbs/myfirstdb", new { userId =
      "Spock", title = "Science Officer" });		
   Console.WriteLine("Document 2: {0}", spockDocument.Resource.SelfLink); 
}

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

Оба документа были сохранены в базе данных myfirstdb, но мы знаем, что Кирк хранится в коллекции от A до M, а Spock хранится в коллекции от N до Z, если наш RangePartitionResolver работает правильно.

Давайте вызовем их из задачи CreateDocumentClient, как показано в следующем коде.

private static async Task CreateDocumentClient() {
   // Create a new instance of the DocumentClient 
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
      await CreateCollections(client);  
      RegisterRangeResolver(client);  
      await CreateDocumentsAcrossPartitions(client); 
   } 
}

Когда приведенный выше код будет выполнен, вы получите следующий вывод.

**** Create Documents Across Partitions **** 
Document 1: dbs/Ic8LAA==/colls/Ic8LAO2DxAA=/docs/Ic8LAO2DxAABAAAAAAAAAA==/ 
Document 2: dbs/Ic8LAA==/colls/Ic8LAP12QAE=/docs/Ic8LAP12QAEBAAAAAAAAAA==/

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

DocumentDB — миграция данных

С помощью инструмента переноса данных DocumentDB вы можете легко перенести данные в DocumentDB. Средство переноса данных DocumentDB — это бесплатная утилита с открытым исходным кодом, которую можно загрузить из центра загрузки Майкрософт https://www.microsoft.com/.

Инструмент миграции поддерживает множество источников данных, некоторые из них перечислены ниже —

После загрузки инструмента переноса данных DocumentDB извлеките zip-файл.

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

Исполняемые файлы

Во-первых, это dt.exe, консольная версия с интерфейсом командной строки, а затем dtui.exe, версия для настольного компьютера с графическим интерфейсом пользователя.

Давайте запустим версию GUI.

Запустить версию GUI

Вы можете увидеть страницу приветствия. Нажмите «Далее» для перехода на страницу с информацией об источнике.

Страница информации об источнике

Здесь вы конфигурируете свой источник данных, и вы можете увидеть множество поддерживаемых вариантов из выпадающего меню.

Укажите источник информации

Когда вы делаете выбор, остальная часть страницы информации об источнике изменяется соответствующим образом.

Импортировать данные в DocumentDB очень просто, используя инструмент переноса данных DocumentDB. Мы рекомендуем вам использовать приведенные выше примеры и использовать другие файлы данных.

DocumentDB — Контроль доступа

DocumentDB предоставляет концепции для управления доступом к ресурсам DocumentDB. Доступ к ресурсам DocumentDB регулируется токеном главного ключа или токеном ресурса. Соединения, основанные на токенах ресурсов, могут получать доступ только к ресурсам, указанным токенами, но не к другим ресурсам. Жетоны ресурсов основаны на разрешениях пользователей.

  • Сначала вы создаете одного или нескольких пользователей, и они определяются на уровне базы данных.

  • Затем вы создаете одно или несколько разрешений для каждого пользователя на основе ресурсов, которые вы хотите разрешить каждому пользователю.

  • Каждое разрешение генерирует маркер ресурса, который разрешает либо только чтение, либо полный доступ к данному ресурсу, и это может быть любой пользовательский ресурс в базе данных.

  • Пользователи определяются на уровне базы данных, а разрешения определяются для каждого пользователя.

  • Пользователи и разрешения применяются ко всем коллекциям в базе данных.

Сначала вы создаете одного или нескольких пользователей, и они определяются на уровне базы данных.

Затем вы создаете одно или несколько разрешений для каждого пользователя на основе ресурсов, которые вы хотите разрешить каждому пользователю.

Каждое разрешение генерирует маркер ресурса, который разрешает либо только чтение, либо полный доступ к данному ресурсу, и это может быть любой пользовательский ресурс в базе данных.

Пользователи определяются на уровне базы данных, а разрешения определяются для каждого пользователя.

Пользователи и разрешения применяются ко всем коллекциям в базе данных.

Давайте рассмотрим простой пример, в котором мы узнаем, как определить пользователей и разрешения для обеспечения детальной безопасности в DocumentDB.

Мы начнем с нового DocumentClient и сделаем запрос к базе данных myfirstdb.

private static async Task CreateDocumentClient() {
   // Create a new instance of the DocumentClient
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
      database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
         'myfirstdb'").AsEnumerable().First();
			
      collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
         "SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();
			
      var alice = await CreateUser(client, "Alice");
      var tom = await CreateUser(client, "Tom");
   }
}

Ниже приведена реализация для CreateUser.

private async static Task<User> CreateUser(DocumentClient client, string userId) {
   Console.WriteLine();
   Console.WriteLine("**** Create User {0} in {1} ****", userId, database.Id);
	
   var userDefinition = new User { Id = userId };
   var result = await client.CreateUserAsync(database.SelfLink, userDefinition);
   var user = result.Resource;
	
   Console.WriteLine("Created new user");
   ViewUser(user);
	
   return user;
}

Шаг 1 — Создайте двух пользователей, Алису и Том, как любой ресурс, который мы создаем, мы создаем объект определения с желаемым Id и вызываем метод create, и в этом случае мы вызываем CreateUserAsync с базой данных SelfLink и userDefinition. Мы получаем результат, из свойства ресурса которого получаем вновь созданный пользовательский объект.

Теперь, чтобы увидеть этих двух новых пользователей в базе данных.

private static void ViewUsers(DocumentClient client) {
   Console.WriteLine(); 
   Console.WriteLine("**** View Users in {0} ****", database.Id);  
	
   var users = client.CreateUserQuery(database.UsersLink).ToList();
   var i = 0;
	
   foreach (var user in users) { 
      i++; 
      Console.WriteLine(); 
      Console.WriteLine("User #{0}", i); 
      ViewUser(user); 
   }
	
   Console.WriteLine();
   Console.WriteLine("Total users in database {0}: {1}", database.Id, users.Count); 
}
  
private static void ViewUser(User user) {
   Console.WriteLine("User ID: {0} ", user.Id); 
   Console.WriteLine("Resource ID: {0} ", user.ResourceId); 
   Console.WriteLine("Self Link: {0} ", user.SelfLink); 
   Console.WriteLine("Permissions Link: {0} ", user.PermissionsLink); 
   Console.WriteLine("Timestamp: {0} ", user.Timestamp); 
}

Шаг 2. Вызовите CreateUserQuery для базы данных UsersLink, чтобы получить список всех пользователей. Затем просмотрите их и просмотрите их свойства.

Теперь мы должны сначала создать их. Допустим, мы хотели предоставить Алисе разрешения на чтение / запись для коллекции MyCollection, но Том может только читать документы в коллекции.

await CreatePermission(client, alice, "Alice Collection Access", PermissionMode.All,
   collection);
	
await CreatePermission(client, tom, "Tom Collection Access", PermissionMode.Read,
   collection);

Шаг 3 — Создайте разрешение для ресурса, который является коллекцией MyCollection, поэтому нам нужно получить этот ресурс SelfLink.

Шаг 4 — Затем создайте Permission.All для этой коллекции для Алисы и Permission.Read для этой коллекции для Tom.

Ниже приводится реализация для CreatePermission.

private async static Task CreatePermission(DocumentClient client, User user,
   string permId, PermissionMode permissionMode, string resourceLink) {
   Console.WriteLine();
   Console.WriteLine("**** Create Permission {0} for {1} ****", permId, user.Id);
	
   var permDefinition = new Permission {
      Id = permId,
      PermissionMode = permissionMode,
      ResourceLink = resourceLink
   };
	
   var result = await client.CreatePermissionAsync(user.SelfLink, permDefinition);
   var perm = result.Resource;
   Console.WriteLine("Created new permission");
   ViewPermission(perm);
}

Как и следовало ожидать, к настоящему времени мы делаем это, создавая объект определения для нового разрешения, который включает Id и allowMode, который является либо Permission.All или Permission.Read, и SelfLink защищаемого ресурса. с разрешения.

Шаг 5 — Вызовите CreatePermissionAsync и получите созданное разрешение из свойства ресурса в результате.

Чтобы просмотреть созданное разрешение, ниже приведена реализация ViewPermissions.

private static void ViewPermissions(DocumentClient client, User user) {
   Console.WriteLine(); 
   Console.WriteLine("**** View Permissions for {0} ****", user.Id);
	
   var perms = client.CreatePermissionQuery(user.PermissionsLink).ToList();
   var i = 0; 
	
   foreach (var perm in perms) {
      i++; 
      Console.WriteLine(); 
      Console.WriteLine("Permission #{0}", i); 
      ViewPermission(perm); 
   }  
	
   Console.WriteLine(); 
   Console.WriteLine("Total permissions for {0}: {1}", user.Id, perms.Count); 
}
  
private static void ViewPermission(Permission perm) {
   Console.WriteLine("Permission ID: {0} ", perm.Id); 
   Console.WriteLine("Resource ID: {0} ", perm.ResourceId); 
   Console.WriteLine("Permission Mode: {0} ", perm.PermissionMode);
   Console.WriteLine("Token: {0} ", perm.Token); 
   Console.WriteLine("Timestamp: {0} ", perm.Timestamp); 
}

На этот раз это запрос разрешения на ссылку разрешения пользователя, и мы просто перечисляем каждое разрешение, возвращаемое пользователю.

Давайте удалим разрешения Алисы и Тома.

await DeletePermission(client, alice, "Alice Collection Access"); 
await DeletePermission(client, tom, "Tom Collection Access");

Ниже приведена реализация DeletePermission.

private async static Task DeletePermission(DocumentClient client, User user,
   string permId) {
   Console.WriteLine(); 
   Console.WriteLine("**** Delete Permission {0} from {1} ****", permId, user.Id);
	
   var query = new SqlQuerySpec {
      QueryText = "SELECT * FROM c WHERE c.id = @id", 
      Parameters = new SqlParameterCollection {
         new SqlParameter { Name = "@id", Value = permId }
      } 
   };
	
   Permission perm = client.CreatePermissionQuery(user.PermissionsLink, query)
      .AsEnumerable().First();  
   await client.DeletePermissionAsync(perm.SelfLink);  
   Console.WriteLine("Deleted permission {0} from user {1}", permId, user.Id); 
}

Шаг 6. Чтобы удалить разрешения, выполните запрос по идентификатору разрешения, чтобы получить SelfLink, а затем используйте SelfLink для удаления разрешения.

Далее давайте удалим самих пользователей. Давайте удалим обоих пользователей.

await DeleteUser(client, "Alice"); 
await DeleteUser(client, "Tom");

Ниже приведена реализация DeleteUser.

private async static Task DeleteUser(DocumentClient client, string userId) {
   Console.WriteLine(); 
   Console.WriteLine("**** Delete User {0} in {1} ****", userId, database.Id);
	
   var query = new SqlQuerySpec { 
      QueryText = "SELECT * FROM c WHERE c.id = @id", 
      Parameters = new SqlParameterCollection {
         new SqlParameter { Name = "@id", Value = userId }
      } 
   };
	
   User user = client.CreateUserQuery(database.SelfLink, query).AsEnumerable().First();  
   await client.DeleteUserAsync(user.SelfLink);  
   Console.WriteLine("Deleted user {0} from database {1}", userId, database.Id); 
}

Шаг 7 — Сначала запросите ее SelfLink, а затем вызовите DeleteUserAsync, чтобы удалить ее пользовательский объект.

Ниже приведена реализация задачи CreateDocumentClient, в которой мы вызываем все вышеуказанные задачи.

private static async Task CreateDocumentClient() {
   // Create a new instance of the DocumentClient
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
      database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
         'myfirstdb'").AsEnumerable().First();
			
      collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
         "SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();
			
      ViewUsers(client);
		
      var alice = await CreateUser(client, "Alice");
      var tom = await CreateUser(client, "Tom");
      ViewUsers(client);
		
      ViewPermissions(client, alice);
      ViewPermissions(client, tom);
		
      string collectionLink = client.CreateDocumentCollectionQuery(database.SelfLink,
         "SELECT VALUE c._self FROM c WHERE c.id = 'MyCollection'")
         .AsEnumerable().First().Value;
			
      await CreatePermission(client, alice, "Alice Collection Access", PermissionMode.All,
         collectionLink);
			
      await CreatePermission(client, tom, "Tom Collection Access", PermissionMode.Read,
         collectionLink);
			
      ViewPermissions(client, alice);
      ViewPermissions(client, tom);
		
      await DeletePermission(client, alice, "Alice Collection Access");
      await DeletePermission(client, tom, "Tom Collection Access");
		
      await DeleteUser(client, "Alice");
      await DeleteUser(client, "Tom");
   }
}

Когда приведенный выше код скомпилирован и выполнен, вы получите следующий вывод.

**** View Users in myfirstdb **** 
 
Total users in database myfirstdb: 0 
 
**** Create User Alice in myfirstdb **** 
Created new user 
          User ID: Alice 
      Resource ID: kV5oAC56NwA= 
        Self Link: dbs/kV5oAA==/users/kV5oAC56NwA=/ 
 Permissions Link: dbs/kV5oAA==/users/kV5oAC56NwA=/permissions/ 
        Timestamp: 12/17/2015 5:44:19 PM
		  
**** Create User Tom in myfirstdb **** 
Created new user 
          User ID: Tom 
      Resource ID: kV5oAALxKgA= 
        Self Link: dbs/kV5oAA==/users/kV5oAALxKgA=/ 
 Permissions Link: dbs/kV5oAA==/users/kV5oAALxKgA=/permissions/ 
        Timestamp: 12/17/2015 5:44:21 PM
		  
**** View Users in myfirstdb ****
  
User #1 
          User ID: Tom 
      Resource ID: kV5oAALxKgA= 
        Self Link: dbs/kV5oAA==/users/kV5oAALxKgA=/ 
 Permissions Link: dbs/kV5oAA==/users/kV5oAALxKgA=/permissions/ 
        Timestamp: 12/17/2015 5:44:21 PM 
		  
User #2 
          User ID: Alice 
      Resource ID: kV5oAC56NwA= 
        Self Link: dbs/kV5oAA==/users/kV5oAC56NwA=/ 
 Permissions Link: dbs/kV5oAA==/users/kV5oAC56NwA=/permissions/ 
        Timestamp: 12/17/2015 5:44:19 PM
		  
Total users in database myfirstdb: 2
  
**** View Permissions for Alice **** 
 
Total permissions for Alice: 0  

**** View Permissions for Tom **** 
 
Total permissions for Tom: 0  

**** Create Permission Alice Collection Access for Alice **** 
Created new permission 
    Permission ID: Alice Collection Access 
      Resource ID: kV5oAC56NwDON1RduEoCAA== 
  Permission Mode: All
            Token: type=resource&ver=1&sig=zB6hfvvleC0oGGbq5cc67w==;Zt3Lx 
Ol14h8pd6/tyF1h62zbZKk9VwEIATIldw4ZyipQGW951kirueAKdeb3MxzQ7eCvDfvp7Y/ZxFpnip/D G 
JYcPyim5cf+dgLvos6fUuiKSFSul7uEKqp5JmJqUCyAvD7w+qt1Qr1PmrJDyAIgbZDBFWGe2VT9FaBH o 
PYwrLjRlnH0AxfbrR+T/UpWMSSHtLB8JvNFZNSH8hRjmQupuTSxCTYEC89bZ/pS6fNmNg8=; 
        Timestamp: 12/17/2015 5:44:28 PM
		  
**** Create Permission Tom Collection Access for Tom **** 
Created new permission 
    Permission ID: Tom Collection Access 
      Resource ID: kV5oAALxKgCMai3JKWdfAA== 
  Permission Mode: Read 
            Token: type=resource&ver=1&sig=ieBHKeyi6EY9ZOovDpe76w==;92gwq 
V4AxKaCJ2dLS02VnJiig/5AEbPcfo1xvOjR10uK3a3FUMFULgsaK8nzxdz6hLVCIKUj6hvMOTOSN8Lt 7 
i30mVqzpzCfe7JO3TYSJEI9D0/5HbMIEgaNJiCu0JPPwsjVecTytiLN56FHPguoQZ7WmUAhVTA0IMP6 p 
jQpLDgJ43ZaG4Zv3qWJiO689balD+egwiU2b7RICH4j6R66UVye+GPxq/gjzqbHwx79t54=; 
        Timestamp: 12/17/2015 5:44:30 PM
		  
**** View Permissions for Alice ****
  
Permission #1 
    Permission ID: Alice Collection Access 
      Resource ID: kV5oAC56NwDON1RduEoCAA== 
  Permission Mode: All 
            Token: type=resource&ver=1&sig=BSzz/VNe9j4IPJ9M31Mf4Q==;Tcq/B 
X50njB1vmANZ/4aHj/3xNkghaqh1OfV95JMi6j4v7fkU+gyWe3mJasO3MJcoop9ixmVnB+RKOhFaSxE l 
P37SaGuIIik7GAWS+dcEBWglMefc95L2YkeNuZsjmmW5b+a8ELCUg7N45MKbpzkp5BrmmGVJ7h4Z4pf D 
rdmehYLuxSPLkr9ndbOOrD8E3bux6TgXCsgYQscpIlJHSKCKHUHfXWBP2Y1LV2zpJmRjis=; 
        Timestamp: 12/17/2015 5:44:28 PM
		  
Total permissions for Alice: 1
  
**** View Permissions for Tom ****
Permission #1 
    Permission ID: Tom Collection Access 
      Resource ID: kV5oAALxKgCMai3JKWdfAA== 
  Permission Mode: Read 
            Token: type=resource&ver=1&sig=NPkWNJp1mAkCASE8KdR6PA==;ur/G2 
V+fDamBmzECux000VnF5i28f8WRbPwEPxD1DMpFPqYcu45wlDyzT5A5gBr3/R3qqYkEVn8bU+een6Gl j 
L6vXzIwsZfL12u/1hW4mJT2as2PWH3eadry6Q/zRXHAxV8m+YuxSzlZPjBFyJ4Oi30mrTXbBAEafZhA 5 
yvbHkpLmQkLCERy40FbIFOzG87ypljREpwWTKC/z8RSrsjITjAlfD/hVDoOyNJwX3HRaz4=; 
        Timestamp: 12/17/2015 5:44:30 PM
		  
Total permissions for Tom: 1
  
**** Delete Permission Alice Collection Access from Alice **** 
Deleted permission Alice Collection Access from user Alice
  
**** Delete Permission Tom Collection Access from Tom **** 
Deleted permission Tom Collection Access from user Tom
  
**** Delete User Alice in myfirstdb **** 
Deleted user Alice from database myfirstdb
  
**** Delete User Tom in myfirstdb **** 
Deleted user Tom from database myfirstdb

DocumentDB — визуализация данных

В этой главе мы узнаем, как визуализировать данные, которые хранятся в DocumentDB. Microsoft предоставила инструмент Power BI Desktop, который преобразует ваши данные в богатые визуальные эффекты. Он также позволяет извлекать данные из различных источников данных, объединять и преобразовывать данные, создавать мощные отчеты и визуализации и публиковать отчеты в Power BI.

В последней версии Power BI Desktop Microsoft также добавила поддержку DocumentDB, в которой теперь вы можете подключаться к своей учетной записи DocumentDB. Вы можете скачать этот инструмент по ссылке, https://powerbi.microsoft.com

Давайте рассмотрим пример, в котором мы визуализируем данные о землетрясениях, импортированные в предыдущей главе.

Шаг 1. После загрузки инструмента запустите рабочий стол Power BI.

запустить Power BI

Шаг 2 — Выберите опцию «Получить данные», которая находится на вкладке «Главная» в группе «Внешние данные», и отобразится страница «Получить данные».

Нажмите Получить данные

Шаг 3. Выберите параметр Microsoft Azure DocumentDB (бета-версия) и нажмите кнопку «Подключиться».

Нажмите Подключиться

Шаг 4. Введите URL-адрес своей учетной записи Azure DocumentDB, базы данных и коллекции, из которой вы хотите визуализировать данные, и нажмите кнопку «ОК».

Если вы подключаетесь к этой конечной точке в первый раз, вам будет предложено ввести ключ учетной записи.

Ключ аккаунта

Шаг 5. Введите ключ учетной записи (первичный ключ), который является уникальным для каждой учетной записи DocumentDB, доступной на портале Azure, и нажмите кнопку Подключиться.

список записей

Когда учетная запись успешно подключена, она будет извлекать данные из указанной базы данных. На панели «Предварительный просмотр» отображается список элементов «Запись». Документ представлен в виде записи в Power BI.

Шаг 6 — Нажмите кнопку «Редактировать», чтобы запустить редактор запросов.

Нажмите кнопку Изменить

Шаг 7. В редакторе запросов Power BI вы должны увидеть столбец «Документ» в центральной панели, нажмите на расширитель в правой части заголовка столбца «Документ» и выберите столбцы, которые вы хотите отобразить.

Нажмите на расширитель

Как вы можете видеть, у нас есть широта и долгота в виде отдельного столбца, но мы визуализируем данные в виде координат широты и долготы.

Шаг 8 — Для этого перейдите на вкладку «Добавить столбец».

нажмите Добавить столбец

Шаг 9 — Выберите Добавить пользовательский столбец, который отобразит следующую страницу.

Добавить пользовательский столбец

Шаг 10 — Укажите имя нового столбца, скажем, LatLong, а также формулу, которая объединит широту и долготу в одном столбце, разделенном запятой. Ниже приводится формула.

Text.From([latitude])&", "&Text.From([longitude])

Шаг 11 — Нажмите OK, чтобы продолжить, и вы увидите, что новый столбец добавлен.

Добавлен новый столбец

Шаг 12 — Перейдите на вкладку «Главная» и нажмите «Закрыть и применить».

нажмите закрыть и применить

Шаг 13. Вы можете создавать отчеты, перетаскивая поля на холст отчета. Вы можете видеть справа, есть две панели — одна панель визуализаций, а другая — панель полей.

создавать отчеты

Давайте создадим вид карты, показывающий местоположение каждого землетрясения.

Шаг 14 — Перетащите визуальный тип карты из панели визуализаций.

Шаг 15. Теперь перетащите поле LatLong с панели «Поля» в свойство «Расположение» на панели «Визуализации». Затем перетащите поле величины в свойство «Значения».

Шаг 16 — Перетащите поле глубины в свойство «Насыщенность цвета».

Глубина поля

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