DocumentDB - Краткое руководство
В этой главе мы кратко обсудим основные концепции NoSQL и документных баз данных. У нас также будет краткий обзор DocumentDB.
База данных документов NoSQL
DocumentDB - это новейшая база данных документов NoSQL от Microsoft, поэтому, когда вы говорите «База данных документов NoSQL», что именно мы подразумеваем под NoSQL и базой данных документов?
SQL означает язык структурированных запросов, который является традиционным языком запросов для реляционных баз данных. SQL часто приравнивают к реляционным базам данных.
Действительно, более полезно думать о базе данных NoSQL как о нереляционной базе данных, поэтому NoSQL действительно означает нереляционную.
Существуют различные типы баз данных NoSQL, которые включают хранилища значений ключей, такие как -
- Хранилище таблиц Azure.
- Колоночные магазины, такие как Cassandra.
- Графические базы данных, такие как NEO4.
- Документируйте базы данных, такие как MongoDB и Azure DocumentDB.
Azure DocumentDB
Microsoft официально запустила Azure DocumentDB апреля 8 - го , 2015, и это , безусловно , можно охарактеризовать как типичную базу данных документа NoSQL. Он очень масштабируемый и работает с документами JSON без схемы.
DocumentDB - это настоящая бессхемная служба базы данных документов NoSQL, разработанная для современных мобильных и веб-приложений.
Он также обеспечивает стабильно быстрое чтение и запись, гибкость схемы и возможность легко масштабировать базу данных вверх и вниз по запросу.
Он не предполагает и не требует какой-либо схемы для индексируемых документов JSON.
DocumentDB автоматически индексирует каждое свойство в документе, как только документ добавляется в базу данных.
DocumentDB позволяет выполнять сложные специальные запросы с использованием языка SQL, и каждый документ мгновенно запрашивается в момент его создания, и вы можете искать по любому свойству в любом месте иерархии документов.
DocumentDB - Цены
DocumentDB оплачивается в зависимости от количества коллекций, содержащихся в учетной записи базы данных. Каждая учетная запись может иметь одну или несколько баз данных, и каждая база данных может иметь практически неограниченное количество коллекций, хотя первоначальная квота по умолчанию составляет 100. Эту квоту можно отменить, обратившись в службу поддержки Azure.
Коллекция - это не только единица измерения масштаба, но и единица стоимости, поэтому в DocumentDB вы платите за коллекцию, емкость которой составляет до 10 ГБ.
Как минимум, вам понадобится одна коллекция S1 для хранения документов в базе данных, которая будет стоить примерно 25 долларов в месяц, которая оплачивается в соответствии с вашей подпиской Azure.
По мере того, как ваша база данных увеличивается в размере и превышает 10 ГБ, вам необходимо приобрести еще одну коллекцию для хранения дополнительных данных.
Каждая коллекция S1 даст вам 250 единиц запросов в секунду, и если этого недостаточно, вы можете масштабировать коллекцию до S2 и получать 1000 единиц запросов в секунду примерно за 50 долларов в месяц.
Вы также можете полностью перейти на S3 и платить около 100 долларов в месяц.
DocumentDB отличается некоторыми уникальными возможностями. Azure DocumentDB предлагает следующие ключевые возможности и преимущества.
Схема бесплатно
В реляционной базе данных каждая таблица имеет схему, которая определяет столбцы и типы данных, которым должна соответствовать каждая строка в таблице.
Напротив, база данных документов не имеет определенной схемы, и каждый документ может быть структурирован по-разному.
Синтаксис SQL
DocumentDB позволяет выполнять сложные специальные запросы с использованием языка SQL, и каждый документ мгновенно запрашивается в момент его создания. Вы можете искать по любому свойству в любом месте иерархии документа.
Настраиваемая согласованность
Он обеспечивает некоторые детальные, четко определенные уровни согласованности, которые позволяют находить разумный компромисс между согласованностью, доступностью и задержкой.
Вы можете выбрать один из четырех четко определенных уровней согласованности для достижения оптимального компромисса между согласованностью и производительностью. Для запросов и операций чтения DocumentDB предлагает четыре различных уровня согласованности:
- Strong
- Bounded-staleness
- Session
- Eventual
Эластичная шкала
Масштабируемость - это главное в NoSQL, и DocumentDB обеспечивает это. DocumentDB уже доказал свой масштаб.
Основные службы, такие как Office OneNote и Xbox, уже поддерживаются DocumentDB с базами данных, содержащими десятки терабайт документов JSON, более миллиона активных пользователей и стабильно работающими с доступностью 99,95%.
Вы можете эластично масштабировать DocumentDB с предсказуемой производительностью, создавая больше единиц по мере роста вашего приложения.
Полностью управляемый
DocumentDB доступна как полностью управляемая облачная платформа в виде службы, работающей в Azure.
Вам просто нечего устанавливать или управлять.
Нет серверов, кабелей, нет операционных систем или обновлений, с которыми нужно иметь дело, нет реплик для настройки.
Microsoft делает всю эту работу и поддерживает работу службы.
Буквально через несколько минут вы можете приступить к работе с DocumentDB, используя только браузер и подписку Azure.
Microsoft предоставляет бесплатную версию Visual Studio, которая также содержит SQL Server, и ее можно загрузить с https://www.visualstudio.com
Установка
Step 1- После завершения загрузки запустите установщик. Появится следующий диалог.
Step 2 - Нажмите кнопку «Установить», и начнется процесс установки.
Step 3 - После успешного завершения процесса установки вы увидите следующий диалог.
Step 4 - Закройте это диалоговое окно и при необходимости перезагрузите компьютер.
Step 5- Теперь откройте Visual Studio из меню «Пуск», в котором откроется диалоговое окно, показанное ниже. Первое время только на подготовку уйдет какое-то время.
Как только все будет сделано, вы увидите главное окно Visual Studio.
Step 6 - Создадим новый проект из File → New → Project.
Step 7 - Выберите Консольное приложение, введите DocumentDBDemo в поле «Имя» и нажмите кнопку «ОК».
Step 8 - В обозревателе решений щелкните свой проект правой кнопкой мыши.
Step 9 - Выберите «Управление пакетами NuGet», чтобы открыть следующее окно в Visual Studio, а в поле ввода «Поиск в Интернете» выполните поиск клиентской библиотеки DocumentDB.
Step 10 - Установите последнюю версию, нажав кнопку установки.
Step 11- Щелкните «Я принимаю». После завершения установки вы увидите сообщение в окне вывода.
Теперь вы готовы начать свое приложение.
Чтобы использовать Microsoft Azure DocumentDB, необходимо создать учетную запись DocumentDB. В этой главе мы создадим учетную запись DocumentDB с помощью портала Azure.
Step 1 - Авторизуйтесь в сети https://portal.azure.com если у вас уже есть подписка Azure, в противном случае вам нужно сначала войти в систему.
Вы увидите основную панель инструментов. Он полностью настраивается, так что вы можете расположить эти плитки так, как вам нравится, изменять их размер, добавлять и удалять плитки для вещей, которые вы часто используете или больше не делаете.
Step 2 - Выберите опцию «Создать» в верхнем левом углу страницы.
Step 3 - Теперь выберите «Данные + хранилище»> «Azure DocumentDB», и вы увидите следующий раздел «Новая учетная запись DocumentDB».
Нам нужно придумать глобально уникальное имя (ID), которое в сочетании с .documents.azure.com представляет собой общедоступную конечную точку для нашей учетной записи DocumentDB. Все базы данных, которые мы создаем под этой учетной записью, могут быть доступны через Интернет с помощью этой конечной точки.
Step 4 - Назовем его azuredocdbdemo и щелкнем Resource Group → new_resource.
Step 5- Выберите местоположение, т. Е. В каком центре обработки данных Microsoft вы хотите разместить эту учетную запись. Выберите место и укажите свой регион.
Step 6 - Установите флажок Закрепить на панели инструментов и просто нажмите кнопку «Создать».
Вы можете видеть, что плитка уже добавлена на панель инструментов и сообщает нам о создании учетной записи. На самом деле настройка новой учетной записи может занять несколько минут, в то время как DocumentDB выделяет конечную точку, подготавливает реплики и выполняет другую работу в фоновом режиме.
Как только это будет сделано, вы увидите панель управления.
Step 7 - Теперь щелкните созданную учетную запись DocumentDB, и вы увидите подробный экран, как показано на следующем рисунке.
Когда вы начинаете программировать с помощью DocumentDB, самым первым шагом является подключение. Итак, чтобы подключиться к вашей учетной записи DocumentDB, вам понадобятся две вещи;
- Endpoint
- Ключ авторизации
Конечная точка
Конечная точка - это URL-адрес вашей учетной записи DocumentDB, который создается путем объединения имени вашей учетной записи DocumentDB с .documents.azure.com. Переходим в Личный кабинет.
Теперь щелкните созданную учетную запись DocumentDB. Вы увидите детали, как показано на следующем изображении.
Когда вы выбираете опцию «Ключи», отображается дополнительная информация, как показано на следующем изображении. Вы также увидите URL-адрес своей учетной записи DocumentDB, которую можно использовать в качестве конечной точки.
Ключ авторизации
Ключ авторизации содержит ваши учетные данные, и есть два типа ключей. Главный ключ обеспечивает полный доступ ко всем ресурсам в учетной записи, в то время как маркеры ресурсов разрешают ограниченный доступ к определенным ресурсам.
Мастер Ключи
Нет ничего невозможного с мастер-ключом. Вы можете удалить всю свою базу данных, если хотите, используя главный ключ.
По этой причине вы определенно не хотите делиться главным ключом или распространять его в клиентских средах. В качестве дополнительной меры безопасности рекомендуется часто менять его.
На самом деле существует два главных ключа для каждой учетной записи базы данных, первичный и вторичный, как показано на скриншоте выше.
Жетоны ресурсов
Вы также можете использовать токены ресурсов вместо главного ключа.
Подключения, основанные на токенах ресурсов, могут получить доступ только к ресурсам, указанным токенами, и никаким другим ресурсам.
Маркеры ресурсов основаны на разрешениях пользователей, поэтому сначала вы создаете одного или нескольких пользователей, и они определяются на уровне базы данных.
Вы создаете одно или несколько разрешений для каждого пользователя в зависимости от ресурсов, к которым вы хотите предоставить каждому пользователю доступ.
Каждое разрешение генерирует токен ресурса, который позволяет либо только для чтения, либо полный доступ к данному ресурсу, и им может быть любой пользовательский ресурс в базе данных.
Переходим в консольное приложение, созданное в главе 3.
Step 1 - Добавьте следующие ссылки в файл Program.cs.
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;
Step 2- Теперь добавьте URL-адрес конечной точки и ключ авторизации. В этом примере мы будем использовать первичный ключ в качестве ключа авторизации.
Обратите внимание, что в вашем случае URL-адрес конечной точки и ключ авторизации должны быть разными.
private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
private const string AuthorizationKey =
"BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
Step 3 - Создайте новый экземпляр DocumentClient в асинхронной задаче под названием CreateDocumentClient и создайте новый DocumentClient.
Step 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.
В этой главе мы узнаем, как создать базу данных. Чтобы использовать Microsoft Azure DocumentDB, у вас должна быть учетная запись DocumentDB, база данных, коллекция и документы. У нас уже есть учетная запись DocumentDB, теперь для создания базы данных у нас есть два варианта:
- Портал Microsoft Azure или
- .Net SDK
Создание базы данных для DocumentDB с помощью портала Microsoft Azure.
Чтобы создать базу данных с помощью портала, выполните следующие действия.
Step 1 - Войдите на портал Azure, и вы увидите панель управления.
Step 2 - Теперь нажмите на созданную учетную запись DocumentDB, и вы увидите детали, как показано на следующем снимке экрана.
Step 3 - Выберите опцию «Добавить базу данных» и укажите идентификатор своей базы данных.
Step 4 - Щелкните ОК.
Вы видите, что база данных добавлена. На данный момент у него нет коллекции, но мы можем добавить коллекции позже, которые являются контейнерами, в которых будут храниться наши документы JSON. Обратите внимание, что у него есть как идентификатор, так и идентификатор ресурса.
Создание базы данных для DocumentDB с помощью .Net SDK
Чтобы создать базу данных с помощью .Net SDK, выполните следующие действия.
Step 1 - Откройте консольное приложение в Visual Studio из предыдущей главы.
Step 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 *******");
}
Step 3- Теперь передайте это определение базы данных в CreateDatabaseAsync и получите результат со свойством Resource. Все методы создания объекта возвращают свойство Resource, которое описывает созданный элемент, которым в данном случае является база данных.
Мы получаем новый объект базы данных из свойства Resource, и он отображается в консоли вместе с идентификатором ресурса, который ему присвоил DocumentDB.
Step 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, первая создается с помощью портала Azure, а вторая база данных создается с помощью .Net SDK. Теперь для просмотра этих баз данных вы можете использовать портал Azure.
Перейдите в свою учетную запись DocumentDB на портале Azure, и теперь вы увидите две базы данных.
Вы также можете просматривать или перечислять базы данных из вашего кода с помощью .Net SDK. Ниже приведены необходимые шаги.
Step 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 (), который фактически выполняет запрос, выполняет итерацию результатов и возвращает их в виде списка.
Step 2 - Вызов метода GetDatabases из задачи CreateDocumentClient после создания экземпляра DocumentClient.
Step 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
Вы можете удалить базу данных или базы данных с портала, а также из кода с помощью .Net SDK. Здесь мы пошагово обсудим, как удалить базу данных в DocumentDB.
Step 1- Перейдите в свою учетную запись DocumentDB на портале Azure. Для демонстрации я добавил еще две базы данных, как показано на следующем снимке экрана.
Step 2- Чтобы удалить любую базу данных, вам нужно щелкнуть эту базу данных. Давайте выберем tempdb, вы увидите следующую страницу, выберите опцию «Удалить базу данных».
Step 3 - Появится подтверждающее сообщение, теперь нажмите кнопку «Да».
Вы увидите, что база данных tempdb больше не доступна на вашей панели инструментов.
Вы также можете удалить базы данных из своего кода с помощью .Net SDK. Чтобы сделать следующие шаги.
Step 1 - Давайте удалим базу данных, указав ID базы данных, которую мы хотим удалить, но нам нужна ее SelfLink.
Step 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);
}
Step 3- На этот раз мы можем вызвать AsEnumerable вместо ToList (), потому что нам фактически не нужен объект списка. Ожидая только результата, вызова AsEnumerable достаточно, чтобы мы могли получить первый объект базы данных, возвращенный запросом с помощью First (). Это объект базы данных для tempdb1, и у него есть SelfLink, который мы можем использовать для вызова DeleteDatabaseAsync, который удаляет базу данных.
Step 4 - Вам также необходимо вызвать задачу DeleteDatabase из задачи CreateDocumentClient после создания экземпляра DocumentClient.
Step 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 остались только две базы данных.
В этой главе мы узнаем, как создать коллекцию. Это похоже на создание базы данных. Вы можете создать коллекцию либо на портале, либо из кода с помощью .Net SDK.
Step 1 - Перейдите на главную панель управления на портале Azure.
Step 2 - Выберите myfirstdb из списка баз данных.
Step 3- Нажмите на опцию «Добавить коллекцию» и укажите идентификатор коллекции. Выберите уровень ценообразования для другого варианта.
Step 4 - Выберем S1 Standard и нажмем Select → OK.
Как видите, MyCollection добавлен в myfirstdb.
Вы также можете создать коллекцию из кода с помощью .Net SDK. Давайте посмотрим на следующие шаги, чтобы добавить коллекции из кода.
Step 1 - Откройте консольное приложение в Visual Studio.
Step 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, который также принимает параметр options, который мы используем здесь, чтобы установить уровень производительности новой коллекции, которую мы вызываем 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
Чтобы удалить коллекцию или коллекции, вы можете сделать то же самое как с портала, так и из кода, используя .Net SDK.
Step 1- Перейдите в свою учетную запись DocumentDB на портале Azure. Для демонстрации я добавил еще две коллекции, как показано на следующем снимке экрана.
Step 2- Чтобы сбросить любую коллекцию, вам нужно щелкнуть по ней. Выберем TempCollection1. Вы увидите следующую страницу, выберите опцию «Удалить коллекцию».
Step 3- Появится подтверждающее сообщение. Теперь нажмите кнопку «Да».
Вы увидите, что TempCollection1 больше не доступен на вашей панели инструментов.
Вы также можете удалять коллекции из своего кода с помощью .Net SDK. Для этого выполните следующие шаги.
Step 1 - Давайте удалим коллекцию, указав ID коллекции, которую мы хотим удалить.
Это обычный шаблон запроса 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.
Step 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
В этой главе мы приступим к работе с реальными документами в коллекции. Вы можете создавать документы с помощью портала Azure или .Net SDK.
Создание документов на портале Azure
Давайте посмотрим на следующие шаги, чтобы добавить документ в вашу коллекцию.
Step 1 - Добавить новую коллекцию Семей ценового уровня S1 в myfirstdb.
Step 2 - Выберите коллекцию «Семьи» и нажмите «Создать документ», чтобы открыть колонку «Новый документ».
Это простой текстовый редактор, который позволяет вам вводить любой JSON для нового документа.
Step 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, обозначенного квадратными скобками. У нас также есть еще один массив для дочерних элементов, хотя в этом примере в массиве только один дочерний элемент.
Step 4 - Нажмите кнопку «Сохранить», чтобы сохранить документ, и мы создали наш первый документ.
Как видите, к нашему JSON было применено красивое форматирование, которое разбивает каждое свойство на отдельную строку с отступом пробела, чтобы передать уровень вложенности каждого свойства.
Портал включает в себя проводник документов, поэтому давайте воспользуемся им сейчас, чтобы получить только что созданный документ.
Step 5- Выберите базу данных и любую коллекцию в базе данных, чтобы просмотреть документы в этой коллекции. В настоящее время у нас есть только одна база данных с именем myfirstdb с одной коллекцией под названием Families, обе из которых были предварительно выбраны здесь в раскрывающихся списках.
По умолчанию в проводнике документов отображается неотфильтрованный список документов в коллекции, но вы также можете искать любой конкретный документ по идентификатору или по нескольким документам на основе поиска с подстановочными знаками частичного идентификатора.
Пока у нас есть только один документ в нашей коллекции, и мы видим его идентификатор на следующем экране, AndersonFamily.
Step 6 - Щелкните идентификатор, чтобы просмотреть документ.
Создание документов с помощью .NET SDK
Как вы знаете, документы - это просто еще один тип ресурсов, и вы уже знакомы с тем, как обращаться с ресурсами с помощью SDK.
Одно большое различие между документами и другими ресурсами заключается в том, что они, конечно, не содержат схемы.
Таким образом, есть много вариантов. Естественно, вы можете просто работать с графами объектов JSON или даже с необработанными строками текста JSON, но вы также можете использовать динамические объекты, которые позволяют выполнять привязку к свойствам во время выполнения, не определяя класс во время компиляции.
Вы также можете работать с реальными объектами C # или Entities, как они называются, которые могут быть классами вашей бизнес-области.
Приступим к созданию документов с помощью .Net SDK. Ниже приведены шаги.
Step 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);
}
}
Step 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;
}
Step 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
Как видите, мы не предоставили идентификатор, однако DocumentDB сгенерировал его для нового документа.
В DocumentDB мы фактически используем SQL для запроса документов, поэтому эта глава посвящена запросам с использованием специального синтаксиса SQL в DocumentDB. Хотя, если вы занимаетесь разработкой .NET, существует также поставщик LINQ, который можно использовать и который может генерировать соответствующий SQL из запроса LINQ.
Запрос документа с помощью портала
На портале Azure есть обозреватель запросов, который позволяет запускать любой SQL-запрос к базе данных DocumentDB.
Мы будем использовать Query Explorer, чтобы продемонстрировать множество различных возможностей и возможностей языка запросов, начиная с самого простого запроса.
Step 1 - В колонке базы данных щелкните, чтобы открыть колонку Query Explorer.
Помните, что запросы выполняются в рамках коллекции, поэтому Query Explorer позволяет вам выбрать коллекцию в этом раскрывающемся списке.
Step 2 - Выберите коллекцию Семей, созданную ранее с помощью портала.
Проводник запросов открывается с помощью этого простого запроса SELECT * FROM c, который просто извлекает все документы из коллекции.
Step 3- Выполните этот запрос, нажав кнопку «Выполнить запрос». После этого вы увидите, что в колонке «Результаты» будет извлечен полный документ.
Запрос документа с использованием .Net SDK
Ниже приведены шаги по запуску некоторых запросов к документам с использованием .Net SDK.
В этом примере мы хотим запросить только что созданные документы, которые мы только что добавили.
Step 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, как раньше, который будет выдавать столько запросов, сколько необходимо для получения всех результатов в одной строке кода.
Step 2 - Вместо этого вызовите AsDocumentQuery, и этот метод вернет объект запроса со свойством HasMoreResults.
Step 3 - Если HasMoreResults имеет значение true, вызовите ExecuteNextAsync, чтобы получить следующий фрагмент, а затем выгрузить все содержимое этого фрагмента.
Step 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.
Step 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
В этой главе мы узнаем, как обновлять документы. Используя портал Azure, вы можете легко обновить документ, открыв документ в проводнике документов и обновив его в редакторе, как текстовый файл.
Нажмите кнопку «Сохранить». Теперь, когда вам нужно изменить документ с помощью .Net SDK, вы можете просто заменить его. Вам не нужно удалять и воссоздавать его, что, помимо утомительности, также изменило бы идентификатор ресурса, чего вы бы не хотели делать, когда вы просто изменяете документ. Вот следующие шаги для обновления документа с помощью .Net SDK.
Давайте посмотрим на следующую задачу ReplaceDocuments, в которой мы будем запрашивать документы, в которых свойство isNew имеет значение true, но мы ничего не получим, потому что их нет. Итак, давайте изменим документы, которые мы добавили ранее, те, чьи имена начинаются с New Customer.
Step 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();
}
Step 2 - Получите документы для обновления, используя тот же запрос STARTSWITH, который дает нам документы, которые мы возвращаем сюда как динамические объекты.
Step 3 - Прикрепите свойство isNew и установите для него значение true для каждого документа.
Step 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. Используя портал Azure, вы можете легко удалить любой документ, открыв его в проводнике документов и нажав кнопку «Удалить».
Появится подтверждающее сообщение. Теперь нажмите кнопку Да, и вы увидите, что документ больше не доступен в вашей учетной записи DocumentDB.
Теперь, когда вы хотите удалить документ с помощью .Net SDK.
Step 1- Это тот же шаблон, который мы видели раньше, когда мы сначала запрашиваем, чтобы получить SelfLinks каждого нового документа. Мы не используем здесь SELECT *, который вернул бы все документы, которые нам не нужны.
Step 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();
}
Step 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, упрощают внесение изменений в вашу модель данных, вам все же следует потратить некоторое время на размышления о своих данных.
У вас есть много вариантов. Естественно, вы можете просто работать с графами объектов JSON или даже с необработанными строками текста JSON, но вы также можете использовать динамические объекты, которые позволяют выполнять привязку к свойствам во время выполнения без определения класса во время компиляции.
Вы также можете работать с реальными объектами C # или Entities, как они называются, которые могут быть классами вашей бизнес-области.
Отношения
Давайте посмотрим на иерархическую структуру документа. Он имеет несколько свойств верхнего уровня, таких как требуемый идентификатор, а также 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, обозначенного квадратными скобками.
У нас также есть еще один массив для дочерних элементов, хотя в этом примере в массиве только один дочерний элемент. Вот как вы моделируете в документе эквивалент отношений «один ко многим».
Вы просто используете массивы, где каждый элемент в массиве может быть простым значением или другим сложным объектом, даже другим массивом.
Таким образом, одна семья может иметь несколько родителей и несколько детей, и если вы посмотрите на дочерние объекты, у них есть свойство домашнего животного, которое само по себе является вложенным массивом для одно-многих отношений между детьми и домашними животными.
Для свойства местоположения мы объединяем три связанных свойства: штат, округ и город в объект.
Встраивание объекта таким образом, а не встраивание массива объектов аналогично взаимно-однозначному отношению между двумя строками в отдельных таблицах в реляционной базе данных.
Встраивание данных
Когда вы начинаете моделировать данные в хранилище документов, таком как DocumentDB, попробуйте рассматривать свои сущности как автономные документы, представленные в JSON. При работе с реляционными базами данных мы всегда нормализуем данные.
Нормализация ваших данных обычно включает взятие объекта, например клиента, и его разбиение на отдельные части данных, такие как контактные данные и адреса.
Чтобы прочитать клиента со всеми его контактными данными и адресами, вам необходимо использовать JOINS для эффективного агрегирования ваших данных во время выполнения.
Теперь давайте посмотрим, как мы моделируем те же данные как автономную сущность в базе данных документов.
{
"id": "1",
"firstName": "Mark",
"lastName": "Upston",
"addresses": [
{
"line1": "232 Main Street",
"line2": "Unit 1",
"city": "Brooklyn",
"state": "NY",
"zip": 11229
}
],
"contactDetails": [
{"email": "[email protected]"},
{"phone": "+1 356 545-86455", "extension": 5555}
]
}
Как видите, мы денормализовали запись о клиенте, где вся информация о клиенте встроена в один документ JSON.
В NoSQL у нас есть бесплатная схема, поэтому вы также можете добавлять контактные данные и адреса в другом формате. В NoSQL вы можете получить запись о клиенте из базы данных за одну операцию чтения. Точно так же обновление записи также является одной операцией записи.
Ниже приведены шаги по созданию документов с помощью .Net SDK.
Step 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);
}
}
Step 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 для этого документа.
Step 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;
}
Step 4- На этот раз мы вызываем CreateDocumentAsync, указывая SelfLink коллекции, в которую мы хотим добавить документ. Мы получаем ответ со свойством ресурса, которое в данном случае представляет новый документ с его свойствами, созданными системой.
В следующей задаче CreateDocuments мы создали три документа.
В первом документе объект 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, который определен в нашем приложении.
Давайте посмотрим на этого клиента, у него есть свойство Id и address, где адрес - это вложенный объект со своими собственными свойствами, включая местоположение, которое является еще одним вложенным объектом.
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. Хотя у нашего объекта клиента есть свойство 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
JSON или JavaScript Object Notation - это облегченный текстовый открытый стандарт, разработанный для удобочитаемого обмена данными, а также простой для машинного анализа и генерации. JSON лежит в основе DocumentDB. Мы передаем JSON по сети, мы храним JSON как JSON и индексируем дерево JSON, позволяя запросы к полному документу JSON.
Формат JSON поддерживает следующие типы данных -
S.No. | Тип и описание |
---|---|
1 | Number Формат с плавающей запятой двойной точности в JavaScript |
2 | String Двойные кавычки Unicode с экранированием обратной косой черты |
3 | Boolean Правда или ложь |
4 | Array Упорядоченная последовательность значений |
5 | Value Это может быть строка, число, истина или ложь, ноль и т. Д. |
6 | Object Неупорядоченный набор пар ключ: значение |
7 | Whitespace Его можно использовать между любой парой токенов |
8 | Null Пустой |
Давайте посмотрим на простой пример типа 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
Microsoft недавно добавила ряд улучшений в способ запроса Azure DocumentDB, например ключевое слово TOP для грамматики SQL, благодаря чему запросы выполняются быстрее и потребляют меньше ресурсов, увеличены ограничения для операторов запросов и добавлена поддержка дополнительных операторов LINQ в .NET SDK.
Давайте посмотрим на простой пример, в котором мы получим только первые две записи. Если у вас есть несколько записей и вы хотите получить только некоторые из них, вы можете использовать ключевое слово Top. В этом примере у нас есть много записей о землетрясениях.
Теперь мы хотим показать только первые две записи.
Step 1 - Перейдите в проводник запросов и запустите этот запрос.
SELECT * FROM c
WHERE c.magnitude > 2.5
Вы увидите, что он получил четыре записи, потому что мы еще не указали ключевое слово TOP.
Step 2- Теперь используйте ключевое слово TOP с тем же запросом. Здесь мы указали ключевое слово TOP, а «2» означает, что нам нужны только две записи.
SELECT TOP 2 * FROM c
WHERE c.magnitude > 2.5
Step 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;
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 поддерживает следующие типы индексации -
- Hash
- Range
Хеш
Индекс хеширования позволяет эффективно запрашивать равенство, т. Е. При поиске документов, в которых заданное свойство равно точному значению, вместо сопоставления по диапазону значений, например, меньше, больше или между.
Вы можете выполнять запросы диапазона с хэш-индексом, но DocumentDB не сможет использовать хеш-индекс для поиска совпадающих документов, и вместо этого потребуется последовательно сканировать каждый документ, чтобы определить, следует ли его выбирать с помощью запроса диапазона.
Вы не сможете отсортировать документы с помощью предложения ORDER BY для свойства, имеющего только хэш-индекс.
Спектр
Индекс диапазона, определенный для свойства, DocumentDB позволяет эффективно запрашивать документы по диапазону значений. Он также позволяет сортировать результаты запроса по этому свойству с помощью ORDER BY.
DocumentDB позволяет определять как хэш, так и индекс диапазона для любого или всех свойств, что обеспечивает эффективные запросы равенства и диапазона, а также ORDER BY.
Политика индексирования
Каждая коллекция имеет политику индексации, которая определяет, какие типы индексов используются для чисел и строк в каждом свойстве каждого документа.
Вы также можете контролировать, будут ли документы индексироваться автоматически при добавлении в коллекцию.
Автоматическое индексирование включено по умолчанию, но вы можете переопределить это поведение при добавлении документа, указав DocumentDB не индексировать этот конкретный документ.
Вы можете отключить автоматическое индексирование, чтобы по умолчанию документы не индексировались при добавлении в коллекцию. Точно так же вы можете переопределить это на уровне документа и указать DocumentDB проиндексировать конкретный документ при его добавлении в коллекцию. Это называется ручным индексированием.
Включить / исключить индексирование
Политика индексации также может определять, какой путь или пути должны быть включены или исключены из индекса. Это полезно, если вы знаете, что есть определенные части документа, которые вы никогда не запрашиваете, а определенные части вы делаете.
В этих случаях вы можете уменьшить накладные расходы на индексацию, указав DocumentDB индексировать только те конкретные части каждого документа, который добавлен в коллекцию.
Автоматическое индексирование
Давайте посмотрим на простой пример автоматической индексации.
Step 1 - Сначала мы создаем коллекцию, называемую автоиндексированием, и без явного указания политики эта коллекция использует политику индексации по умолчанию, что означает, что для этой коллекции включено автоматическое индексирование.
Здесь мы используем маршрутизацию на основе идентификаторов для самосвязи с базой данных, поэтому нам не нужно знать идентификатор ресурса или запрашивать его перед созданием коллекции. Мы можем просто использовать идентификатор базы данных mydb.
Step 2 - Теперь создадим два документа, оба на фамилию Упстон.
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 не индексировать этот документ, несмотря на политику индексирования коллекции.
У нас есть разные типы запросов для обоих документов в конце.
Step 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==/
Как видите, у нас есть два таких документа, но запрос возвращает только один для Mark, потому что тот для Mark не проиндексирован. Если мы снова запросим без предложения WHERE для извлечения всех документов в коллекции, то мы получим набор результатов с обоими документами, и это потому, что неиндексированные документы всегда возвращаются запросами, у которых нет предложения WHERE.
Мы также можем получить неиндексированные документы по их идентификатору или ссылке на себя. Поэтому, когда мы запрашиваем документ Марка по его идентификатору, MARK, мы видим, что DocumentDB возвращает документ, даже если он не проиндексирован в коллекции.
Ручное индексирование
Давайте посмотрим на простой пример ручного индексирования путем отмены автоматического индексирования.
Step 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");
}
Step 2- Теперь мы снова создадим те же два документа, что и раньше. На этот раз мы не будем предоставлять никаких специальных параметров запроса для документа Марка, поскольку из-за политики индексирования коллекции этот документ не будет проиндексирован.
Step 3 - Теперь, когда мы добавляем второй документ для Mark, мы используем RequestOptions с IndexingDirective.Include, чтобы сообщить DocumentDB, что он должен индексировать этот документ, что переопределяет политику индексирования коллекции, которая говорит, что этого не должно быть.
У нас есть разные типы запросов для обоих документов в конце.
Step 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==/
Опять же, запрос возвращает только один из двух документов, но на этот раз он возвращает Jane Doe, которую мы явно просили проиндексировать. Но опять же, как и раньше, при запросе без предложения WHERE извлекаются все документы в коллекции, включая неиндексированный документ для Mark. Мы также можем запросить неиндексированный документ по его идентификатору, который DocumentDB возвращает, даже если он не проиндексирован.
Microsoft добавила geospatial support, который позволяет вам хранить данные о местоположении в ваших документах и выполнять пространственные вычисления для расстояния и пересечений между точками и многоугольниками.
Пространственные данные описывают положение и форму объектов в пространстве.
Обычно его можно использовать для обозначения местонахождения человека, достопримечательности, границы города или озера.
Общие варианты использования часто включают запросы близости. Например, «найти все университеты рядом с моим текущим местоположением».
А Pointобозначает одну позицию в пространстве, которая представляет точное местоположение, например, адрес конкретного университета. Точка представлена в 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
Когда ваша база данных начинает превышать 10 ГБ, вы можете масштабироваться, просто создавая новые коллекции, а затем распределяя или разделяя ваши данные по все большему количеству коллекций.
Рано или поздно одной коллекции, имеющей емкость 10 ГБ, будет недостаточно для размещения вашей базы данных. 10 ГБ может показаться не очень большим числом, но помните, что мы храним документы JSON, которые представляют собой простой текст, и вы можете уместить множество текстовых документов в 10 ГБ, даже если учесть накладные расходы на хранилище для индексов.
Когда речь идет о масштабируемости, проблема не только в хранилище. Максимальная пропускная способность, доступная для коллекции, составляет две с половиной тысячи единиц запросов в секунду, которые вы получаете с коллекцией S3. Следовательно, если вам нужна более высокая пропускная способность, вам также потребуется горизонтальное масштабирование путем разделения на несколько коллекций. Масштабируемое секционирование также называютhorizontal partitioning.
Существует множество подходов, которые можно использовать для разделения данных с помощью Azure DocumentDB. Ниже приведены наиболее распространенные стратегии -
- Дополнительное разбиение
- Разделение диапазона
- Разбиение на разделы поиска
- Разбиение хэша
Дополнительное разбиение
Дополнительное разделение - это простейшая стратегия, поскольку нет ключа раздела. Часто это хороший выбор для начала, когда вы во многих вещах не уверены. Вы можете не знать, потребуется ли вам когда-либо масштабироваться за пределы одной коллекции, или сколько коллекций вам может понадобиться добавить, или как быстро вам может потребоваться их добавить.
Дополнительное разделение начинается с единственной коллекции, и ключа раздела нет.
Коллекция начинает расти, а затем увеличивается еще немного, а затем еще немного, пока вы не приблизитесь к пределу в 10 ГБ.
Когда вы достигнете 90-процентной емкости, вы перейдете в новую коллекцию и начнете использовать ее для новых документов.
Как только ваша база данных масштабируется до большего количества коллекций, вы, вероятно, захотите перейти к стратегии, основанной на ключе раздела.
Когда вы это сделаете, вам нужно будет повторно сбалансировать данные, переместив документы в разные коллекции в зависимости от стратегии, на которую вы переходите.
Разделение диапазона
Одна из наиболее распространенных стратегий - разделение по диапазонам. При таком подходе вы определяете диапазон значений, в который может попасть ключ раздела документа, и направляете документ в коллекцию, соответствующую этому диапазону.
Даты очень часто используются с этой стратегией, когда вы создаете коллекцию для хранения документов, которые попадают в определенный диапазон дат. Когда вы определяете достаточно маленькие диапазоны, когда вы уверены, что ни одна коллекция никогда не превысит свой предел в 10 ГБ. Например, может быть сценарий, когда одна коллекция может разумно обрабатывать документы в течение всего месяца.
Также может случиться так, что большинство пользователей запрашивают текущие данные, которые могут быть данными за этот месяц или, возможно, за последний месяц, но пользователи редко ищут гораздо более старые данные. Итак, вы начнете в июне с коллекции S3, которая является самой дорогой коллекцией, которую вы можете купить, и обеспечивает лучшую пропускную способность, которую вы можете получить.
В июле вы покупаете еще одну коллекцию S3 для хранения июльских данных, а также масштабируете июньские данные до менее дорогой коллекции S2. Затем, в августе, вы получаете еще одну коллекцию S3 и уменьшаете июль до S2, а июнь - до S1. Это происходит месяц за месяцем, когда вы всегда сохраняете доступность текущих данных для высокой пропускной способности, а более старые данные - при более низкой пропускной способности.
Пока запрос предоставляет ключ раздела, будет запрошена только запрашиваемая коллекция, а не все коллекции в базе данных, как это происходит при дополнительном разделении.
Разбиение на разделы поиска
При помощи поиска по разделам вы можете определить карту разделов, которая направляет документы в определенные коллекции на основе их ключа раздела. Например, вы можете разделить по регионам.
Храните все документы США в одной коллекции, все европейские документы в другой коллекции и все документы из любого другого региона в третьей коллекции.
Используйте эту карту разделов, и преобразователь разделов поиска сможет определить, в какой коллекции создать документ и какие коллекции запрашивать, на основе ключа раздела, который является свойством региона, содержащимся в каждом документе.
Разбиение хэша
При разделении по хешу разделы назначаются на основе значения хеш-функции, что позволяет равномерно распределять запросы и данные по нескольким разделам.
Это обычно используется для разделения данных, созданных или потребляемых большим количеством отдельных клиентов, и полезно для хранения профилей пользователей, элементов каталога и т. Д.
Давайте посмотрим на простой пример разделения по диапазонам с использованием RangePartitionResolver, поставляемого .NET SDK.
Step 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” });
}
Step 2 - Зарегистрируйте преобразователь диапазона для базы данных.
Step 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 во втором диапазоне. Итак, вы можете думать об этом закодированном значении здесь как о подстановочном знаке для сопоставления ключа раздела.
Step 4- После создания преобразователя зарегистрируйте его для базы данных с текущим DocumentClient. Для этого просто назначьте его свойству словаря PartitionResolver.
Мы будем создавать и запрашивать документы в базе данных, а не в коллекции, как вы обычно делаете, преобразователь будет использовать эту карту для маршрутизации запросов в соответствующие коллекции.
Теперь создадим несколько документов. Сначала мы создадим один для пользователя Kirk, а затем один для Спока.
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, а Спок сохраняется в коллекции от 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 Data Migration Tool - это бесплатная утилита с открытым исходным кодом, которую можно загрузить из Центра загрузки Microsoft.https://www.microsoft.com/
Инструмент миграции поддерживает множество источников данных, некоторые из них перечислены ниже -
- SQL Server
- Файлы JSON
- Плоские файлы значений, разделенных запятыми (CSV)
- MongoDB
- Хранилище таблиц Azure
- Amazon DynamoDB
- HBase и даже другие базы данных DocumentDB
После загрузки инструмента переноса данных DocumentDB распакуйте zip-файл.
Вы можете увидеть два исполняемых файла в этой папке, как показано на следующем снимке экрана.
Во-первых, это dt.exe, консольная версия с интерфейсом командной строки, а затем dtui.exe, настольная версия с графическим пользовательским интерфейсом.
Запустим версию с графическим интерфейсом.
Вы можете увидеть страницу приветствия. Нажмите «Далее» для перехода на страницу с информацией об источнике.
Здесь вы настраиваете свой источник данных, и вы можете увидеть множество поддерживаемых вариантов в раскрывающемся меню.
Когда вы сделаете выбор, остальная часть страницы с информацией об источнике изменится соответствующим образом.
Импортировать данные в 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;
}
Step 1- Создайте двух пользователей, Алису и Тома, как любой ресурс, который мы создаем, мы создаем объект определения с желаемым идентификатором и вызываем метод 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);
}
Step 2- Вызовите CreateUserQuery в отношении UsersLink базы данных, чтобы получить список всех пользователей. Затем пролистайте их и просмотрите их свойства.
Теперь нам нужно сначала их создать. Итак, предположим, что мы хотели разрешить Алисе права на чтение / запись для коллекции MyCollection, но Том может только читать документы в коллекции.
await CreatePermission(client, alice, "Alice Collection Access", PermissionMode.All,
collection);
await CreatePermission(client, tom, "Tom Collection Access", PermissionMode.Read,
collection);
Step 3- Создайте разрешение для ресурса, который является коллекцией MyCollection, поэтому нам нужно получить для этого ресурса SelfLink.
Step 4 - Затем создайте Permission.All для этой коллекции для Алисы и Permission. Прочтите эту коллекцию для 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 и permissionMode, которым является Permission.All или Permission.Read, и SelfLink защищаемого ресурса. по разрешению.
Step 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);
}
Step 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);
}
Step 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. Microsoft предоставила инструмент Power BI Desktop, который преобразует ваши данные в богатые визуальные эффекты. Он также позволяет извлекать данные из различных источников данных, объединять и преобразовывать данные, создавать мощные отчеты и визуализации и публиковать отчеты в Power BI.
В последней версии Power BI Desktop Microsoft также добавила поддержку DocumentDB, в которой теперь вы можете подключиться к своей учетной записи DocumentDB. Вы можете скачать этот инструмент по ссылке,https://powerbi.microsoft.com
Давайте рассмотрим пример, в котором мы будем визуализировать данные о землетрясениях, импортированные в предыдущей главе.
Step 1 - После загрузки инструмента запустите рабочий стол Power BI.
Step 2 - Нажмите «Получить данные» на вкладке «Главная» в группе «Внешние данные», и откроется страница «Получить данные».
Step 3 - Выберите опцию Microsoft Azure DocumentDB (бета) и нажмите кнопку «Подключиться».
Step 4 - Введите URL-адрес вашей учетной записи, базы данных и коллекции Azure DocumentDB, из которых вы хотите визуализировать данные, и нажмите ОК.
Если вы подключаетесь к этой конечной точке впервые, вам будет предложено ввести ключ учетной записи.
Step 5 - Введите ключ учетной записи (первичный ключ), который является уникальным для каждой учетной записи DocumentDB, доступной на портале Azure, а затем нажмите «Подключиться».
Когда учетная запись будет успешно подключена, она получит данные из указанной базы данных. На панели предварительного просмотра отображается список элементов записи, документ представлен как тип записи в Power BI.
Step 6 - Нажмите кнопку «Изменить», чтобы запустить редактор запросов.
Step 7 - В редакторе запросов Power BI вы должны увидеть столбец «Документ» на центральной панели, щелкните расширитель в правой части заголовка столбца «Документ» и выберите столбцы, которые необходимо отобразить.
Как видите, у нас есть широта и долгота как отдельные столбцы, но мы визуализируем данные в форме координат широты и долготы.
Step 8 - Для этого нажмите вкладку «Добавить столбец».
Step 9 - Выберите Добавить настраиваемый столбец, который отобразит следующую страницу.
Step 10- Укажите имя нового столбца, скажем, LatLong, а также формулу, которая объединит широту и долготу в один столбец, разделенный запятой. Ниже приводится формула.
Text.From([latitude])&", "&Text.From([longitude])
Step 11 - Нажмите OK, чтобы продолжить, и вы увидите, что новый столбец добавлен.
Step 12 - Перейдите на вкладку «Главная» и нажмите «Закрыть и применить».
Step 13- Вы можете создавать отчеты, перетаскивая поля на холст отчета. Вы можете видеть, что справа есть две панели: одна панель визуализаций, а другая панель полей.
Давайте создадим вид карты, показывающий местоположение каждого землетрясения.
Step 14 - Перетащите визуальный тип карты с панели «Визуализации».
Step 15- Теперь перетащите поле LatLong из панели Fields в свойство Location на панели Visualizations. Затем перетащите поле величины в свойство Values.
Step 16 - Перетащите поле глубины в свойство насыщенности цвета.
Теперь вы увидите визуальный элемент карты, показывающий набор пузырьков, указывающих местоположение каждого землетрясения.