DocumentDB - Guia Rápido
Neste capítulo, discutiremos brevemente os principais conceitos em torno de NoSQL e bancos de dados de documentos. Também teremos uma visão geral rápida do Banco de Dados de Documentos.
Banco de dados de documentos NoSQL
DocumentDB é o mais novo banco de dados de documentos NoSQL da Microsoft, então, quando você diz banco de dados de documentos NoSQL, o que exatamente queremos dizer com NoSQL e banco de dados de documentos?
SQL significa Structured Query Language, que é a linguagem de consulta tradicional de bancos de dados relacionais. SQL geralmente é equiparado a bancos de dados relacionais.
É realmente mais útil pensar em um banco de dados NoSQL como um banco de dados não relacional, então NoSQL realmente significa não relacional.
Existem diferentes tipos de bancos de dados NoSQL que incluem armazenamentos de valores-chave, como -
- Armazenamento de tabelas do Azure.
- Lojas baseadas em colunas como Cassandra.
- Bancos de dados gráficos como NEO4.
- Bancos de dados de documentos como MongoDB e Azure DocumentDB.
Azure DocumentDB
Microsoft lançado oficialmente Azure DocumentDB em 08 de abril th , 2015, e certamente pode ser caracterizado como um banco de dados típico documento NoSQL. É extremamente escalonável e funciona com documentos JSON sem esquema.
O DocumentDB é um verdadeiro serviço de banco de dados de documentos NoSQL sem esquema projetado para aplicativos móveis e da web modernos.
Ele também oferece leituras e gravações consistentemente rápidas, flexibilidade de esquema e a capacidade de escalar facilmente um banco de dados para cima e para baixo sob demanda.
Ele não assume nem exige nenhum esquema para os documentos JSON que indexa.
O Banco de Dados de Documentos indexa automaticamente todas as propriedades de um documento assim que o documento é adicionado ao banco de dados.
O DocumentDB permite consultas ad-hoc complexas usando uma linguagem SQL, e cada documento pode ser consultado instantaneamente no momento em que é criado, e você pode pesquisar em qualquer propriedade em qualquer lugar na hierarquia do documento.
Banco de Dados de Documentos - Preços
O Banco de Dados de Documentos é cobrado com base no número de coleções contidas em uma conta de banco de dados. Cada conta pode ter um ou mais bancos de dados e cada banco de dados pode ter um número virtualmente ilimitado de coleções, embora haja uma cota padrão inicial de 100. Essa cota pode ser aumentada entrando em contato com o suporte do Azure.
Uma coleção não é apenas uma unidade de escala, mas também uma unidade de custo, portanto, no Banco de Dados de Documentos você paga por coleção, que tem uma capacidade de armazenamento de até 10 GB.
No mínimo, você precisará de uma coleção S1 para armazenar documentos em um banco de dados que custará cerca de US $ 25 por mês, que será cobrado em sua assinatura do Azure.
Conforme seu banco de dados cresce em tamanho e excede 10 GB, você precisará comprar outra coleção para conter os dados adicionais.
Cada coleção S1 lhe dará 250 unidades de solicitação por segundo e, se isso não for suficiente, você pode dimensionar a coleção até S2 e obter 1000 unidades de solicitação por segundo por cerca de US $ 50 por mês.
Você também pode aumentar para um S3 e pagar cerca de US $ 100 por mês.
O DocumentDB se destaca com alguns recursos muito exclusivos. O Azure DocumentDB oferece os seguintes recursos e benefícios principais.
Esquema Livre
Em um banco de dados relacional, cada tabela possui um esquema que define as colunas e os tipos de dados aos quais cada linha da tabela deve estar em conformidade.
Em contraste, um banco de dados de documentos não tem esquema definido e cada documento pode ser estruturado de maneira diferente.
Sintaxe SQL
O DocumentDB permite consultas ad-hoc complexas usando a linguagem SQL, e cada documento pode ser consultado instantaneamente no momento em que é criado. Você pode pesquisar qualquer propriedade em qualquer lugar na hierarquia do documento.
Consistência ajustável
Ele fornece alguns níveis de consistência granulares e bem definidos, o que permite que você faça compensações sólidas entre consistência, disponibilidade e latência.
Você pode selecionar entre quatro níveis de consistência bem definidos para obter o equilíbrio ideal entre consistência e desempenho. Para consultas e operações de leitura, o Banco de Dados de Documentos oferece quatro níveis de consistência distintos -
- Strong
- Bounded-staleness
- Session
- Eventual
Escala Elástica
Escalabilidade é o nome do jogo com NoSQL, e o DocumentDB oferece. O DocumentDB já provou sua escala.
Os principais serviços como Office OneNote e Xbox já contam com o suporte do DocumentDB com bancos de dados contendo dezenas de terabytes de documentos JSON, mais de um milhão de usuários ativos e operando de forma consistente com 99,95% de disponibilidade.
Você pode escalar elasticamente o Banco de Dados de Documentos com desempenho previsível criando mais unidades à medida que seu aplicativo cresce.
Totalmente Gerenciado
O DocumentDB está disponível como uma plataforma totalmente gerenciada baseada em nuvem como um serviço em execução no Azure.
Simplesmente não há nada para você instalar ou gerenciar.
Não há servidores, cabos, sistemas operacionais ou atualizações para lidar, nem réplicas para configurar.
A Microsoft faz todo esse trabalho e mantém o serviço em execução.
Em literalmente minutos, você pode começar a trabalhar com o DocumentDB usando apenas um navegador e uma assinatura do Azure.
A Microsoft fornece uma versão gratuita do Visual Studio que também contém o SQL Server e pode ser baixado em https://www.visualstudio.com
Instalação
Step 1- Assim que o download for concluído, execute o instalador. A seguinte caixa de diálogo será exibida.
Step 2 - Clique no botão Instalar e iniciará o processo de instalação.
Step 3 - Assim que o processo de instalação for concluído com sucesso, você verá a seguinte caixa de diálogo.
Step 4 - Feche esta caixa de diálogo e reinicie o computador, se necessário.
Step 5- Agora abra o Visual studio a partir do menu inicial, que abrirá a caixa de diálogo abaixo. Pela primeira vez, levará algum tempo apenas para a preparação.
Assim que tudo estiver feito, você verá a janela principal do Visual Studio.
Step 6 - Vamos criar um novo projeto em Arquivo → Novo → Projeto.
Step 7 - Selecione Aplicativo de console, insira DocumentDBDemo no campo Nome e clique no botão OK.
Step 8 - No Solution Explorer, clique com o botão direito em seu projeto.
Step 9 - Selecione Gerenciar Pacotes NuGet, que abrirá a janela a seguir no Visual Studio e, na caixa de entrada Pesquisar Online, pesquise por Biblioteca de Cliente DocumentDB.
Step 10 - Instale a versão mais recente clicando no botão instalar.
Step 11- Clique em “Aceito”. Assim que a instalação for concluída, você verá a mensagem na janela de saída.
Agora você está pronto para iniciar seu aplicativo.
Para usar o Microsoft Azure DocumentDB, você deve criar uma conta DocumentDB. Neste capítulo, criaremos uma conta DocumentDB usando o portal do Azure.
Step 1 - Faça login no online https://portal.azure.com se você já tiver uma assinatura do Azure, caso contrário, será necessário entrar primeiro.
Você verá o painel principal. É totalmente personalizável para que você possa organizar esses blocos da maneira que quiser, redimensioná-los, adicionar e remover blocos para coisas que você usa com frequência ou não faz mais.
Step 2 - Selecione a opção 'Novo' no canto superior esquerdo da página.
Step 3 - Agora selecione a opção Dados + Armazenamento> Banco de Dados do Azure e você verá a seguinte seção Nova conta do Banco de Dados de Documentos.
Precisamos criar um nome (ID) exclusivo globalmente, que combinado com .documents.azure.com é o ponto de extremidade endereçável publicamente para nossa conta DocumentDB. Todos os bancos de dados que criamos sob essa conta podem ser acessados pela Internet usando este endpoint.
Step 4 - Vamos chamá-lo de azuredocdbdemo e clicar em Grupo de recursos → new_resource.
Step 5- Escolha o local, ou seja, em qual data center da Microsoft você deseja que esta conta seja hospedada. Selecione o local e escolha sua região.
Step 6 - Marque a caixa de seleção Fixar no painel e vá em frente e clique no botão Criar.
Você pode ver que o bloco já foi adicionado ao Painel e nos informa que a conta está sendo criada. Na verdade, pode levar alguns minutos para configurar as coisas para uma nova conta enquanto o Banco de Dados de Documentos aloca o terminal, provisiona réplicas e executa outro trabalho em segundo plano.
Uma vez feito isso, você verá o painel.
Step 7 - Agora clique na conta do Banco de Dados de Documentos criada e você verá uma tela detalhada conforme a imagem a seguir.
Quando você começa a programar no Banco de Dados de Documentos, a primeira etapa é conectar. Portanto, para se conectar à sua conta do Banco de Dados de Documentos, você precisará de duas coisas;
- Endpoint
- Chave de Autorização
Endpoint
Endpoint é o URL para sua conta do Banco de Dados de Documentos e é construído combinando o nome da conta do Banco de Dados de Documentos com .documents.azure.com. Vamos para o painel.
Agora, clique na conta do Banco de Dados de Documentos criada. Você verá os detalhes conforme mostrado na imagem a seguir.
Quando você seleciona a opção 'Chaves', ela exibe informações adicionais, conforme mostrado na imagem a seguir. Você também verá o URL de sua conta do Banco de Dados de Documentos, que pode ser usado como seu terminal.
Chave de Autorização
A chave de autorização contém suas credenciais e existem dois tipos de chaves. A chave mestra permite acesso total a todos os recursos da conta, enquanto os tokens de recursos permitem acesso restrito a recursos específicos.
Chaves Mestras
Não há nada que você não possa fazer com uma chave mestra. Você pode explodir seu banco de dados inteiro se quiser, usando a chave mestra.
Por esse motivo, você definitivamente não quer compartilhar a chave mestra ou distribuí-la para ambientes de cliente. Como medida de segurança adicional, é uma boa ideia alterá-lo com frequência.
Na verdade, existem duas chaves mestras para cada conta de banco de dados, a primária e a secundária, conforme destacado na captura de tela acima.
Tokens de recursos
Você também pode usar tokens de recursos em vez de uma chave mestra.
As conexões baseadas em tokens de recursos podem acessar apenas os recursos especificados pelos tokens e nenhum outro recurso.
Os tokens de recursos são baseados nas permissões do usuário, portanto, primeiro você cria um ou mais usuários, e estes são definidos no nível do banco de dados.
Você cria uma ou mais permissões para cada usuário, com base nos recursos que deseja permitir que cada usuário acesse.
Cada permissão gera um token de recurso que permite acesso somente leitura ou total a um determinado recurso e que pode ser qualquer recurso de usuário no banco de dados.
Vamos para o aplicativo de console criado no capítulo 3.
Step 1 - Adicione as seguintes referências no arquivo Program.cs.
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;
Step 2- Agora adicione o URL do endpoint e a chave de autorização. Neste exemplo, usaremos a chave primária como chave de autorização.
Observe que, no seu caso, o URL do endpoint e a chave de autorização devem ser diferentes.
private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
private const string AuthorizationKey =
"BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
Step 3 - Crie uma nova instância do DocumentClient na tarefa assíncrona chamada CreateDocumentClient e instancie o novo DocumentClient.
Step 4 - Chame sua tarefa assíncrona de seu método Main.
A seguir está o arquivo Program.cs completo até agora.
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);
}
}
}
Neste capítulo, aprendemos como se conectar a uma conta DocumentDB e criar uma instância da classe DocumentClient.
Neste capítulo, aprenderemos como criar um banco de dados. Para usar o Microsoft Azure DocumentDB, você deve ter uma conta DocumentDB, um banco de dados, uma coleção e documentos. Já temos uma conta DocumentDB, agora para criar o banco de dados temos duas opções -
- Portal do Microsoft Azure ou
- .Net SDK
Crie um banco de dados para DocumentDB usando o Portal do Microsoft Azure
Para criar um banco de dados usando o portal, a seguir estão as etapas.
Step 1 - Faça login no portal do Azure e você verá o painel.
Step 2 - Agora clique na conta do Banco de Dados de Documentos criada e você verá os detalhes conforme mostrado na imagem a seguir.
Step 3 - Selecione a opção Adicionar banco de dados e forneça o ID para seu banco de dados.
Step 4 - Clique em OK.
Você pode ver que o banco de dados foi adicionado. No momento, ele não tem coleção, mas podemos adicionar coleções posteriormente, que são os contêineres que irão armazenar nossos documentos JSON. Observe que ele tem um ID e um ID de recurso.
Crie um banco de dados para DocumentDB usando .Net SDK
Para criar um banco de dados usando .Net SDK, a seguir estão as etapas.
Step 1 - Abra o aplicativo de console no Visual Studio do último capítulo.
Step 2- Crie o novo banco de dados criando um novo objeto de banco de dados. Para criar um novo banco de dados, precisamos apenas atribuir a propriedade Id, que definimos como “mynewdb” em uma tarefa 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- Agora passe esta definição de banco de dados para CreateDatabaseAsync e obtenha um resultado com uma propriedade de Recurso. Todos os métodos de criação de objeto retornam uma propriedade Resource que descreve o item que foi criado, que neste caso é um banco de dados.
Obtemos o novo objeto de banco de dados da propriedade Resource e ele é exibido no console junto com a ID do recurso que o Banco de Dados de Documentos atribuiu a ele.
Step 4 - Agora chame a tarefa CreateDatabase a partir da tarefa CreateDocumentClient depois que DocumentClient for instanciado.
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
await CreateDatabase(client);
}
A seguir está o arquivo Program.cs completo até agora.
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 *******");
}
}
}
Quando o código acima for compilado e executado, você receberá a seguinte saída que contém os IDs do banco de dados e dos recursos.
******** Create Database *******
Database Id: mynewdb; Rid: ltpJAA==
******** Database Created *******
Até agora, criamos dois bancos de dados em nossa conta DocumentDB, o primeiro é criado usando o portal do Azure, enquanto o segundo banco de dados é criado usando .Net SDK. Agora, para exibir esses bancos de dados, você pode usar o portal do Azure.
Acesse sua conta DocumentDB no portal do Azure e você verá dois bancos de dados agora.
Você também pode visualizar ou listar os bancos de dados de seu código usando .Net SDK. A seguir estão as etapas envolvidas.
Step 1 - Emita uma Consulta de banco de dados sem parâmetros que retorna uma lista completa, mas você também pode passar uma consulta para procurar um banco de dados específico ou bancos de dados específicos.
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);
}
Você verá que existem vários desses métodos CreateQuery para localizar coleções, documentos, usuários e outros recursos. Na verdade, esses métodos não executam a consulta, apenas definem a consulta e retornam um objeto iterável.
É a chamada para ToList () que realmente executa a consulta, itera os resultados e os retorna em uma lista.
Step 2 - Chame o método GetDatabases a partir da tarefa CreateDocumentClient depois que DocumentClient for instanciado.
Step 3 - Você também precisa comentar a tarefa CreateDatabase ou alterar o id do banco de dados, caso contrário, você receberá uma mensagem de erro informando que o banco de dados existe.
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
//await CreateDatabase(client);
GetDatabases(client);
}
A seguir está o arquivo Program.cs completo até agora.
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);
}
}
}
Quando o código acima for compilado e executado, você receberá a seguinte saída que contém os IDs do banco de dados e dos recursos de ambos os bancos de dados. No final, você também verá o número total de bancos de dados.
******** Get Databases List ********
Database Id: myfirstdb; Rid: Ic8LAA==
Database Id: mynewdb; Rid: ltpJAA==
Total databases: 2
Você pode eliminar um banco de dados ou bancos de dados do portal, bem como do código, usando .Net SDK. Aqui, discutiremos, passo a passo, como eliminar um banco de dados no Banco de Dados de Documentos.
Step 1- Vá para sua conta DocumentDB no portal do Azure. Para fins de demonstração, adicionei mais dois bancos de dados, conforme visto na captura de tela a seguir.
Step 2- Para eliminar qualquer banco de dados, você precisa clicar nesse banco de dados. Vamos selecionar tempdb, você verá a página seguinte, selecione a opção 'Excluir banco de dados'.
Step 3 - Irá exibir a mensagem de confirmação, agora clique no botão 'Sim'.
Você verá que o tempdb não está mais disponível em seu painel.
Você também pode excluir bancos de dados de seu código usando .Net SDK. Para fazer a seguir estão as etapas.
Step 1 - Vamos excluir o banco de dados especificando o ID do banco de dados que queremos excluir, mas precisamos de seu SelfLink.
Step 2 - Estamos chamando CreateDatabaseQuery como antes, mas desta vez estamos fornecendo uma consulta para retornar apenas um banco de dados com o ID 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- Desta vez, podemos chamar AsEnumerable em vez de ToList () porque, na verdade, não precisamos de um objeto de lista. Esperando apenas o resultado, chamar AsEnumerable é suficiente para que possamos obter o primeiro objeto de banco de dados retornado pela consulta com First (). Este é o objeto de banco de dados para tempdb1 e tem um SelfLink que podemos usar para chamar DeleteDatabaseAsync que exclui o banco de dados.
Step 4 - Você também precisa chamar a tarefa DeleteDatabase a partir da tarefa CreateDocumentClient depois que DocumentClient é instanciado.
Step 5 - Para visualizar a lista de bancos de dados após excluir o banco de dados especificado, vamos chamar o método GetDatabases novamente.
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
//await CreateDatabase(client);
GetDatabases(client);
await DeleteDatabase(client);
GetDatabases(client);
}
A seguir está o arquivo Program.cs completo até agora.
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);
}
}
}
Quando o código acima for compilado e executado, você receberá a seguinte saída que contém os IDs de banco de dados e recursos dos três bancos de dados e o número total de bancos de dados.
******** 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
Depois de excluir o banco de dados, você também verá no final que apenas dois bancos de dados permanecem na conta do Banco de Dados de Documentos.
Neste capítulo, aprenderemos como criar uma coleção. É semelhante a criar um banco de dados. Você pode criar uma coleção a partir do portal ou do código usando .Net SDK.
Step 1 - Vá para o painel principal no portal do Azure.
Step 2 - Selecione myfirstdb na lista de bancos de dados.
Step 3- Clique na opção 'Adicionar coleção' e especifique o ID da coleção. Selecione o nível de preço para uma opção diferente.
Step 4 - Vamos selecionar S1 Standard e clicar em Selecionar → botão OK.
Como você pode ver, MyCollection é adicionado ao myfirstdb.
Você também pode criar uma coleção do código usando .Net SDK. Vamos dar uma olhada nas etapas a seguir para adicionar coleções do código.
Step 1 - Abra o aplicativo Console no Visual Studio.
Step 2 - Para criar uma coleção, primeiro recupere o banco de dados myfirstdb por seu ID na tarefa 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");
}
}
A seguir está a implementação da tarefa 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);
}
Criamos um novo objeto DocumentCollection que define a nova coleção com o Id desejado para o método CreateDocumentCollectionAsync que também aceita um parâmetro de opções que estamos usando aqui para definir o nível de desempenho da nova coleção, que estamos chamando de offerType.
O padrão é S1 e como não passamos um offerType, para MyCollection1, então esta será uma coleção S1 e para MyCollection2 passamos S2, o que torna esta uma S2 conforme mostrado acima.
A seguir está a implementação do método 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);
}
A seguir está a implementação completa do arquivo program.cs para coleções.
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);
}
}
}
Quando o código acima for compilado e executado, você receberá a seguinte saída que contém todas as informações relacionadas à coleta.
**** 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
Para descartar uma coleção ou coleções, você pode fazer o mesmo no portal e também no código usando o .Net SDK.
Step 1- Vá para sua conta DocumentDB no portal do Azure. Para fins de demonstração, adicionei mais duas coleções, como visto na imagem a seguir.
Step 2- Para soltar qualquer coleção, você precisa clicar nessa coleção. Vamos selecionar TempCollection1. Você verá a página a seguir, selecione a opção 'Excluir coleção'.
Step 3- Irá exibir a mensagem de confirmação. Agora clique no botão 'Sim'.
Você verá que TempCollection1 não está mais disponível em seu painel.
Você também pode excluir coleções de seu código usando .Net SDK. Para fazer isso, a seguir estão as seguintes etapas.
Step 1 - Vamos deletar a coleção especificando o ID da coleção que queremos deletar.
É o padrão usual de consulta por Id para obter os selfLinks necessários para excluir um recurso.
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);
}
Aqui, vemos a maneira preferida de construir uma consulta parametrizada. Não estamos codificando o collectionId, portanto, este método pode ser usado para excluir qualquer coleção. Estamos consultando por uma coleção específica por Id, onde o parâmetro Id é definido neste SqlParameterCollection atribuído à propriedade do parâmetro deste SqlQuerySpec.
Em seguida, o SDK faz o trabalho de construir a string de consulta final para DocumentDB com o collectionId embutido nele.
Step 2 - Execute a consulta e use seu SelfLink para excluir a coleção da tarefa 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");
}
}
A seguir está a implementação completa do arquivo 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);
}
}
}
Quando o código acima for compilado e executado, você receberá a seguinte saída.
**** Delete Collection TempCollection in myfirstdb ****
Deleted collection TempCollection from database myfirstdb
Neste capítulo, vamos trabalhar com documentos reais em uma coleção. Você pode criar documentos usando o portal do Azure ou .Net SDK.
Criação de documentos com o Portal do Azure
Vamos dar uma olhada nas etapas a seguir para adicionar documentos à sua coleção.
Step 1 - Adicionar novas famílias de coleção do nível de preços S1 em myfirstdb.
Step 2 - Selecione a coleção Famílias e clique na opção Criar Documento para abrir a folha Novo Documento.
Este é apenas um editor de texto simples que permite digitar qualquer JSON para um novo documento.
Step 3 - Como esta é a entrada de dados brutos, vamos inserir nosso primeiro documento.
{
"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
}
Ao entrar no documento acima, você verá a tela a seguir.
Observe que fornecemos um id para o documento. O valor de id é sempre obrigatório e deve ser exclusivo em todos os outros documentos da mesma coleção. Quando você o deixa de fora, o Banco de Dados de Documentos gera automaticamente um para você usando um GUID ou um Identificador Globalmente Único.
O id é sempre uma string e não pode ser um número, data, booleano ou outro objeto, e não pode ter mais de 255 caracteres.
Observe também a estrutura hierárquica do documento, que possui algumas propriedades de nível superior, como o id necessário, bem como lastName e isRegistered, mas também possui propriedades aninhadas.
Por exemplo, a propriedade Parents é fornecida como uma matriz JSON conforme denotado pelos colchetes. Também temos outro array para filhos, embora haja apenas um filho no array neste exemplo.
Step 4 - Clique no botão 'Salvar' para salvar o documento e criamos nosso primeiro documento.
Como você pode ver, uma boa formatação foi aplicada ao nosso JSON, que divide cada propriedade em sua própria linha recuada com um espaço em branco para transmitir o nível de aninhamento de cada propriedade.
O portal inclui um Explorador de Documentos, então vamos usá-lo agora para recuperar o documento que acabamos de criar.
Step 5- Escolha um banco de dados e qualquer coleção dentro do banco de dados para visualizar os documentos dessa coleção. Atualmente, temos apenas um banco de dados chamado myfirstdb com uma coleção chamada Famílias, ambas pré-selecionadas aqui nos menus suspensos.
Por padrão, o Document Explorer exibe uma lista não filtrada de documentos na coleção, mas você também pode pesquisar qualquer documento específico por ID ou vários documentos com base em uma pesquisa curinga de um ID parcial.
Temos apenas um documento em nossa coleção até agora e vemos seu ID na tela a seguir, AndersonFamily.
Step 6 - Clique no ID para visualizar o documento.
Criação de documentos com o .NET SDK
Como você sabe, os documentos são apenas outro tipo de recurso e você já se familiarizou com como tratar os recursos usando o SDK.
A única grande diferença entre documentos e outros recursos é que, obviamente, eles não têm esquemas.
Portanto, existem muitas opções. Naturalmente, você pode apenas trabalhar com gráficos de objeto JSON ou até mesmo strings brutas de texto JSON, mas também pode usar objetos dinâmicos que permitem vincular a propriedades em tempo de execução sem definir uma classe em tempo de compilação.
Você também pode trabalhar com objetos C # reais, ou Entities, como são chamados, que podem ser suas classes de domínio de negócios.
Vamos começar a criar documentos usando .Net SDK. A seguir estão as etapas.
Step 1 - Instancie o DocumentClient, então iremos consultar o banco de dados myfirstdb e, em seguida, consultar a coleção MyCollection, que armazenamos nesta coleção de variáveis privadas para que seja acessível em toda a classe.
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 - Crie alguns documentos na tarefa 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();
}
O primeiro documento será gerado a partir deste objeto dinâmico. Pode parecer JSON, mas é claro que não é. Este é o código C # e estamos criando um objeto .NET real, mas não há definição de classe. Em vez disso, as propriedades são inferidas da maneira como o objeto é inicializado.
Observe que não fornecemos uma propriedade Id para este documento.
Agora, vamos dar uma olhada em CreateDocument. Parece o mesmo padrão que vimos para a criação de bancos de dados e coleções.
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- Desta vez, chamamos CreateDocumentAsync especificando o SelfLink da coleção à qual queremos adicionar o documento. Recebemos uma resposta com uma propriedade de recurso que, neste caso, representa o novo documento com suas propriedades geradas pelo sistema.
O objeto Document é uma classe definida no SDK que herda do recurso e, portanto, tem todas as propriedades de recurso comuns, mas também inclui as propriedades dinâmicas que definem o próprio documento sem esquema.
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();
}
Quando o código acima for compilado e executado, você receberá a seguinte saída.
**** 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
Como você pode ver, não fornecemos um Id, no entanto, o Banco de Dados de Documentos gerou este para nós para o novo documento.
No DocumentDB, na verdade usamos SQL para consultar documentos, portanto, este capítulo trata de consultas usando a sintaxe SQL especial no DocumentDB. Embora se você estiver fazendo desenvolvimento em .NET, também há um provedor LINQ que pode ser usado e que pode gerar SQL apropriado a partir de uma consulta LINQ.
Consultando documento usando o Portal
O portal do Azure tem um Explorador de Consultas que permite executar qualquer consulta SQL em seu banco de dados DocumentDB.
Usaremos o Query Explorer para demonstrar os muitos recursos e recursos diferentes da linguagem de consulta, começando com a consulta mais simples possível.
Step 1 - Na folha do banco de dados, clique para abrir a folha Explorador de Consultas.
Lembre-se de que as consultas são executadas dentro do escopo de uma coleção e, portanto, o Query Explorer permite que você escolha a coleção neste menu suspenso.
Step 2 - Selecione a coleção de Famílias que é criada anteriormente usando o portal.
O Query Explorer é aberto com esta consulta simples SELECT * FROM c, que simplesmente recupera todos os documentos da coleção.
Step 3- Execute esta consulta clicando no botão 'Executar consulta'. Em seguida, você verá que o documento completo é recuperado na folha Resultados.
Consultando documento usando .Net SDK
A seguir estão as etapas para executar algumas consultas de documentos usando .Net SDK.
Neste exemplo, queremos consultar os documentos recém-criados que acabamos de adicionar.
Step 1 - Chame CreateDocumentQuery, passando a coleção para executar a consulta por seu SelfLink e o texto da consulta.
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();
}
Essa consulta também está retornando todos os documentos em toda a coleção, mas não estamos chamando .ToList em CreateDocumentQuery como antes, o que emitiria quantas solicitações fossem necessárias para obter todos os resultados em uma linha de código.
Step 2 - Em vez disso, chame AsDocumentQuery e este método retorna um objeto de consulta com uma propriedade HasMoreResults.
Step 3 - Se HasMoreResults for verdadeiro, chame ExecuteNextAsync para obter o próximo bloco e, em seguida, despeje todo o conteúdo desse bloco.
Step 4- Você também pode consultar usando LINQ em vez de SQL, se preferir. Aqui, definimos uma consulta LINQ em q, mas ela não será executada até executarmos .ToList nela.
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();
}
O SDK converterá nossa consulta LINQ em sintaxe SQL para DocumentDB, gerando uma cláusula SELECT e WHERE com base em nossa sintaxe LINQ
Step 5 - Agora chame as consultas acima da tarefa 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);
}
}
Quando o código acima for executado, você receberá a seguinte saída.
**** 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
Neste capítulo, aprenderemos como atualizar os documentos. Usando o portal do Azure, você pode atualizar facilmente o documento abrindo o documento no Explorador de documentos e atualizando-o no editor como um arquivo de texto.
Clique no botão 'Salvar'. Agora, quando você precisar alterar um documento usando o .Net SDK, basta substituí-lo. Você não precisa deletar e recriá-lo, o que além de ser tedioso, também alteraria a id do recurso, o que você não gostaria de fazer quando está apenas modificando um documento. Aqui estão as seguintes etapas para atualizar o documento usando .Net SDK.
Vamos dar uma olhada na tarefa ReplaceDocuments a seguir, onde consultaremos os documentos em que a propriedade isNew é verdadeira, mas não obteremos nenhum porque não há nenhum. Portanto, vamos modificar os documentos que adicionamos anteriormente, aqueles cujos nomes começam com Novo cliente.
Step 1 - Adicione a propriedade isNew a esses documentos e defina seu valor como 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 - Pegue os documentos a serem atualizados usando a mesma consulta STARTSWITH e isso nos dá os documentos, que estamos recebendo aqui como objetos dinâmicos.
Step 3 - Anexe a propriedade isNew e defina-a como true para cada documento.
Step 4 - Chame ReplaceDocumentAsync, passando o SelfLink do documento, junto com o documento atualizado.
Agora, apenas para provar que funcionou, consulte os documentos em que isNew é igual a true. Vamos chamar as consultas acima da tarefa 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);
}
}
Quando o código acima for compilado e executado, você receberá a seguinte saída.
**** 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
Neste capítulo, aprenderemos como excluir um documento de sua conta do Banco de Dados de Documentos. Usando o Portal do Azure, você pode excluir facilmente qualquer documento abrindo o documento no Document Explorer e clicando na opção 'Excluir'.
Ele exibirá a mensagem de confirmação. Agora pressione o botão Sim e você verá que o documento não está mais disponível em sua conta do Banco de Dados de Documentos.
Agora, quando você deseja excluir um documento usando .Net SDK.
Step 1- É o mesmo padrão que vimos antes, onde consultaremos primeiro para obter os SelfLinks de cada novo documento. Não usamos SELECT * aqui, que retornaria os documentos em sua totalidade, dos quais não precisamos.
Step 2 - Em vez disso, estamos apenas selecionando os SelfLinks em uma lista e, em seguida, chamamos DeleteDocumentAsync para cada SelfLink, um de cada vez, para excluir os documentos da coleção.
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 - Agora vamos chamar o DeleteDocuments acima da tarefa 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);
}
}
Quando o código acima for executado, você receberá a seguinte saída.
***** Delete Documents *****
Quering for documents to be deleted
Found 2 documents to be deleted
Deleted 2 new customer documents
Embora os bancos de dados sem esquema, como o Banco de Dados de Documentos, facilitem muito a aceitação de alterações em seu modelo de dados, você ainda deve passar algum tempo pensando em seus dados.
Você tem muitas opções. Naturalmente, você pode apenas trabalhar com gráficos de objeto JSON ou até mesmo strings brutas de texto JSON, mas também pode usar objetos dinâmicos que permitem vincular a propriedades em tempo de execução sem definir uma classe em tempo de compilação.
Você também pode trabalhar com objetos C # reais, ou Entities, como são chamados, que podem ser suas classes de domínio de negócios.
Relacionamentos
Vamos dar uma olhada na estrutura hierárquica do documento. Ele tem algumas propriedades de nível superior, como o id necessário, bem como lastName e isRegistered, mas também possui propriedades aninhadas.
{
"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
}
Por exemplo, a propriedade Parents é fornecida como uma matriz JSON conforme denotado pelos colchetes.
Também temos outro array para filhos, embora haja apenas um filho no array neste exemplo. Portanto, é assim que você modela o equivalente a relacionamentos um-para-muitos em um documento.
Você simplesmente usa matrizes onde cada elemento da matriz pode ser um valor simples ou outro objeto complexo, até mesmo outra matriz.
Portanto, uma família pode ter vários pais e vários filhos e, se você olhar para os objetos filhos, eles têm uma propriedade de animal de estimação que é uma matriz aninhada para um relacionamento um para muitos entre crianças e animais de estimação.
Para a propriedade location, estamos combinando três propriedades relacionadas, o estado, o condado e a cidade em um objeto.
Incorporar um objeto dessa maneira, em vez de incorporar uma matriz de objetos, é semelhante a ter um relacionamento um-para-um entre duas linhas em tabelas separadas em um banco de dados relacional.
Incorporando Dados
Ao começar a modelar dados em um armazenamento de documentos, como o Banco de Dados de Documentos, tente tratar suas entidades como documentos autocontidos representados em JSON. Ao trabalhar com bancos de dados relacionais, sempre normalizamos os dados.
Normalizar seus dados normalmente envolve pegar uma entidade, como um cliente, e dividi-la em partes discretas de dados, como detalhes de contato e endereços.
Para ler um cliente, com todos os seus detalhes de contato e endereços, você precisa usar JOINS para agregar de forma eficaz seus dados em tempo de execução.
Agora, vamos dar uma olhada em como modelaríamos os mesmos dados como uma entidade independente em um banco de dados de documentos.
{
"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}
]
}
Como você pode ver, desnormalizamos o registro do cliente, onde todas as informações do cliente são incorporadas em um único documento JSON.
No NoSQL, temos um esquema gratuito, para que você também possa adicionar detalhes de contato e endereços em formatos diferentes. No NoSQL, você pode recuperar um registro de cliente do banco de dados em uma única operação de leitura. Da mesma forma, atualizar um registro também é uma única operação de gravação.
A seguir estão as etapas para criar documentos usando .Net SDK.
Step 1- Instancie o DocumentClient. Em seguida, iremos consultar o banco de dados myfirstdb e também consultar a coleção MyCollection, que armazenamos nesta coleção de variáveis privadas para que seja acessível em toda a classe.
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 - Crie alguns documentos na tarefa 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();
}
O primeiro documento será gerado a partir deste objeto dinâmico. Pode parecer JSON, mas é claro que não é. Este é o código C # e estamos criando um objeto .NET real, mas não há definição de classe. Em vez disso, as propriedades são inferidas da maneira como o objeto é inicializado. Você pode notar também que não fornecemos uma propriedade Id para este documento.
Step 3 - Agora vamos dar uma olhada no CreateDocument e ele se parece com o mesmo padrão que vimos para criar bancos de dados e coleções.
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- Desta vez, chamamos CreateDocumentAsync especificando o SelfLink da coleção à qual queremos adicionar o documento. Recebemos uma resposta com uma propriedade de recurso que, neste caso, representa o novo documento com suas propriedades geradas pelo sistema.
Na tarefa CreateDocuments a seguir, criamos três documentos.
No primeiro documento, o objeto Document é uma classe definida no SDK que herda do recurso e, portanto, possui todas as propriedades de recurso comuns, mas também inclui as propriedades dinâmicas que definem o próprio documento sem esquema.
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();
}
Este segundo documento funciona apenas com uma string JSON bruta. Agora entramos em uma sobrecarga para CreateDocument que usa o JavaScriptSerializer para desserializar a string em um objeto, que então passa para o mesmo método CreateDocument que usamos para criar o primeiro documento.
No terceiro documento, usamos o objeto C # Customer que é definido em nossa aplicação.
Vamos dar uma olhada neste cliente, ele tem uma propriedade Id e endereço em que o endereço é um objeto aninhado com suas próprias propriedades, incluindo localização, que é outro objeto aninhado.
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; }
}
}
Também temos atributos de propriedade JSON em vigor porque queremos manter as convenções adequadas em ambos os lados da cerca.
Então, acabo de criar meu objeto New Customer junto com seus objetos filho aninhados e chamo CreateDocument mais uma vez. Embora nosso objeto de cliente tenha uma propriedade Id, não fornecemos um valor para ele e, portanto, o Banco de Dados de Documentos gerou um com base no GUID, assim como fez para os dois documentos anteriores.
Quando o código acima for compilado e executado, você receberá a seguinte saída.
**** 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 ou JavaScript Object Notation é um padrão aberto baseado em texto leve projetado para intercâmbio de dados legível por humanos e também fácil para máquinas analisar e gerar. JSON está no centro do DocumentDB. Transmitimos JSON pela rede, armazenamos JSON como JSON e indexamos a árvore JSON, permitindo consultas em todo o documento JSON.
O formato JSON suporta os seguintes tipos de dados -
S.No. | Tipo e descrição |
---|---|
1 | Number Formato de ponto flutuante de precisão dupla em JavaScript |
2 | String Unicode entre aspas duplas com escape de barra invertida |
3 | Boolean Verdadeiro ou falso |
4 | Array Uma sequência ordenada de valores |
5 | Value Pode ser uma string, um número, verdadeiro ou falso, nulo, etc. |
6 | Object Uma coleção não ordenada de pares chave: valor |
7 | Whitespace Pode ser usado entre qualquer par de tokens |
8 | Null Vazio |
Vamos dar uma olhada em um exemplo simples do tipo DateTime. Adicione a data de nascimento à classe do cliente.
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; }
}
Podemos armazenar, recuperar e consultar usando DateTime conforme mostrado no código a seguir.
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();
}
Quando o código acima for compilado e executado, e o documento for criado, você verá que a data de nascimento foi adicionada agora.
**** 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
A Microsoft adicionou recentemente uma série de melhorias sobre como você pode consultar o Azure DocumentDB, como a palavra-chave TOP para gramática SQL, o que tornou as consultas mais rápidas e consumiram menos recursos, aumentou os limites para operadores de consulta e adicionou suporte para operadores LINQ adicionais em o .NET SDK.
Vamos dar uma olhada em um exemplo simples no qual recuperaremos apenas os dois primeiros registros. Se você tiver vários registros e quiser recuperar apenas alguns deles, poderá usar a palavra-chave Top. Neste exemplo, temos muitos registros de terremotos.
Agora queremos mostrar os primeiros dois registros apenas
Step 1 - Vá para o explorador de consultas e execute esta consulta.
SELECT * FROM c
WHERE c.magnitude > 2.5
Você verá que recuperou quatro registros porque ainda não especificamos a palavra-chave TOP.
Step 2- Agora use a palavra-chave TOP com a mesma consulta. Aqui especificamos a palavra-chave TOP e '2' significa que queremos apenas dois registros.
SELECT TOP 2 * FROM c
WHERE c.magnitude > 2.5
Step 3 - Agora execute esta consulta e você verá que apenas dois registros são recuperados.
Da mesma forma, você pode usar a palavra-chave TOP no código usando .Net SDK. A seguir está a implementação.
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();
}
A seguir está a tarefa CreateDocumentClient na qual são instanciados o banco de dados DocumentClient e terremoto.
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);
}
}
Quando o código acima for compilado e executado, você verá que apenas três registros são recuperados.
**** Query Documents (paged results) ****
Quering for all documents
PublicId: 2015p947400; Magnitude: 2.515176918;
PublicId: 2015p947373; Magnitude: 1.506774108;
PublicId: 2015p947329; Magnitude: 1.593394461;
O Microsoft Azure DocumentDB oferece suporte à consulta de documentos usando SQL sobre documentos JSON. Você pode classificar os documentos da coleção em números e strings usando uma cláusula ORDER BY em sua consulta. A cláusula pode incluir um argumento ASC / DESC opcional para especificar a ordem em que os resultados devem ser recuperados.
Vamos dar uma olhada no exemplo a seguir, no qual temos um documento 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
}
]
}
A seguir está a consulta SQL para classificar o resultado em ordem decrescente.
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
Quando a consulta acima for executada, você receberá a seguinte saída.
[
{
"description": "Grapes, red or green (European type, such as Thompson
seedless), raw",
"foodGroup": "Fruits and Fruit Juices",
"servingDescription": "NLEA serving",
"servingWeight": 126
}
]
Por padrão, o Banco de Dados de Documentos indexa automaticamente todas as propriedades de um documento assim que o documento é adicionado ao banco de dados. No entanto, você pode assumir o controle e ajustar sua própria política de indexação que reduz a sobrecarga de armazenamento e processamento quando há documentos e / ou propriedades específicos que nunca precisam ser indexados.
A política de indexação padrão que diz ao Banco de Dados de Documentos para indexar todas as propriedades automaticamente é adequada para muitos cenários comuns. Mas você também pode implementar uma política personalizada que exerce controle fino sobre exatamente o que é indexado e o que não é, e outras funcionalidades com relação à indexação.
O DocumentDB suporta os seguintes tipos de indexação -
- Hash
- Range
Cerquilha
O índice de hash permite uma consulta eficiente de igualdade, ou seja, ao pesquisar documentos em que uma determinada propriedade é igual a um valor exato, em vez de corresponder a um intervalo de valores como menor que, maior que ou entre.
Você pode realizar consultas de intervalo com um índice hash, mas o Banco de Dados de Documentos não será capaz de usar o índice hash para encontrar documentos correspondentes e, em vez disso, precisará digitalizar sequencialmente cada documento para determinar se ele deve ser selecionado pela consulta de intervalo.
Você não poderá classificar seus documentos com uma cláusula ORDER BY em uma propriedade que tem apenas um índice hash.
Alcance
Índice de intervalo definido para a propriedade, o Banco de Dados de Documentos permite consultar documentos com eficiência em relação a um intervalo de valores. Ele também permite que você classifique os resultados da consulta nessa propriedade, usando ORDER BY.
O DocumentDB permite que você defina um hash e um índice de intervalo em qualquer uma ou todas as propriedades, o que permite consultas de igualdade e intervalo eficientes, bem como ORDER BY.
Política de Indexação
Cada coleção tem uma política de indexação que determina quais tipos de índices são usados para números e strings em cada propriedade de cada documento.
Você também pode controlar se os documentos são indexados automaticamente ou não à medida que são adicionados à coleção.
A indexação automática é ativada por padrão, mas você pode substituir esse comportamento ao adicionar um documento, dizendo ao Banco de Dados de Documentos para não indexar esse documento específico.
Você pode desabilitar a indexação automática para que, por padrão, os documentos não sejam indexados quando adicionados à coleção. Da mesma forma, você pode substituir isso no nível do documento e instruir o Banco de Dados de Documentos a indexar um documento específico ao adicioná-lo à coleção. Isso é conhecido como indexação manual.
Incluir / Excluir Indexação
Uma política de indexação também pode definir qual caminho ou caminhos devem ser incluídos ou excluídos do índice. Isso é útil se você sabe que há certas partes de um documento que você nunca consulta e certas partes que você faz.
Nesses casos, você pode reduzir a sobrecarga de indexação dizendo ao Banco de Dados de Documentos para indexar apenas aquelas partes específicas de cada documento adicionado à coleção.
Indexação Automática
Vamos dar uma olhada em um exemplo simples de indexação automática.
Step 1 - Primeiro criamos uma coleção chamada autoindexing e sem fornecer explicitamente uma política, essa coleção usa a política de indexação padrão, o que significa que a indexação automática está habilitada nesta coleção.
Aqui, estamos usando o roteamento baseado em ID para o auto-link do banco de dados, portanto não precisamos saber seu ID de recurso ou consultá-lo antes de criar a coleção. Podemos apenas usar o ID do banco de dados, que é mydb.
Step 2 - Agora vamos criar dois documentos, ambos com o sobrenome Upston.
private async static Task AutomaticIndexing(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("**** Override Automatic Indexing ****");
// Create collection with automatic indexing
var collectionDefinition = new DocumentCollection {
Id = "autoindexing"
};
var collection = await client.CreateDocumentCollectionAsync("dbs/mydb",
collectionDefinition);
// Add a document (indexed)
dynamic indexedDocumentDefinition = new {
id = "MARK",
firstName = "Mark",
lastName = "Upston",
addressLine = "123 Main Street",
city = "Brooklyn",
state = "New York",
zip = "11229",
};
Document indexedDocument = await client
.CreateDocumentAsync("dbs/mydb/colls/autoindexing", indexedDocumentDefinition);
// Add another document (request no indexing)
dynamic unindexedDocumentDefinition = new {
id = "JANE",
firstName = "Jane",
lastName = "Upston",
addressLine = "123 Main Street",
city = "Brooklyn",
state = "New York",
zip = "11229",
};
Document unindexedDocument = await client
.CreateDocumentAsync("dbs/mydb/colls/autoindexing", unindexedDocumentDefinition,
new RequestOptions { IndexingDirective = IndexingDirective.Exclude });
//Unindexed document won't get returned when querying on non-ID (or selflink) property
var doeDocs = client.CreateDocumentQuery("dbs/mydb/colls/autoindexing", "SELECT *
FROM c WHERE c.lastName = 'Doe'").ToList();
Console.WriteLine("Documents WHERE lastName = 'Doe': {0}", doeDocs.Count);
// Unindexed document will get returned when using no WHERE clause
var allDocs = client.CreateDocumentQuery("dbs/mydb/colls/autoindexing",
"SELECT * FROM c").ToList();
Console.WriteLine("All documents: {0}", allDocs.Count);
// Unindexed document will get returned when querying by ID (or self-link) property
Document janeDoc = client.CreateDocumentQuery("dbs/mydb/colls/autoindexing",
"SELECT * FROM c WHERE c.id = 'JANE'").AsEnumerable().FirstOrDefault();
Console.WriteLine("Unindexed document self-link: {0}", janeDoc.SelfLink);
// Delete the collection
await client.DeleteDocumentCollectionAsync("dbs/mydb/colls/autoindexing");
}
Este primeiro, para Mark Upston, é adicionado à coleção e é imediatamente indexado automaticamente com base na política de indexação padrão.
Mas quando o segundo documento para Mark Upston é adicionado, passamos as opções de solicitação com IndexingDirective.Exclude, que instrui explicitamente o Banco de Dados de Documentos a não indexar este documento, apesar da política de indexação da coleção.
Temos diferentes tipos de consultas para ambos os documentos no final.
Step 3 - Vamos chamar a tarefa AutomaticIndexing de 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);
}
}
Quando o código acima for compilado e executado, você receberá a seguinte saída.
**** Override Automatic Indexing ****
Documents WHERE lastName = 'Upston': 1
All documents: 2
Unindexed document self-link: dbs/kV5oAA==/colls/kV5oAOEkfQA=/docs/kV5oAOEkfQACA
AAAAAAAAA==/
Como você pode ver, temos dois desses documentos, mas a consulta retorna apenas aquele para Marcos porque o de Marcos não está indexado. Se consultarmos novamente, sem uma cláusula WHERE para recuperar todos os documentos na coleção, obteremos um conjunto de resultados com ambos os documentos e isso ocorre porque os documentos não indexados sempre são retornados por consultas que não têm cláusula WHERE.
Também podemos recuperar documentos não indexados por meio de seu ID ou link próprio. Portanto, quando consultamos o documento de Mark por seu ID, MARK, vemos que o Banco de Dados de Documentos retorna o documento, embora não esteja indexado na coleção.
Indexação Manual
Vamos dar uma olhada em um exemplo simples de indexação manual substituindo a indexação automática.
Step 1- Primeiro, criaremos uma coleção chamada indexação manual e substituiremos a política padrão desabilitando explicitamente a indexação automática. Isso significa que, a menos que solicitemos de outra forma, novos documentos adicionados a esta coleção não serão indexados.
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- Agora vamos criar novamente os mesmos dois documentos de antes. Não forneceremos nenhuma opção de solicitação especial para o documento de Mark neste momento, devido à política de indexação da coleção, este documento não será indexado.
Step 3 - Agora, quando adicionamos o segundo documento para Mark, usamos RequestOptions com IndexingDirective.Include para dizer ao DocumentDB que ele deve indexar este documento, o que substitui a política de indexação da coleção que diz que não deveria.
Temos diferentes tipos de consultas para ambos os documentos no final.
Step 4 - Vamos chamar a tarefa ManualIndexing de 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);
}
}
Quando o código acima for compilado e executado, você receberá a seguinte saída.
**** Manual Indexing ****
Documents WHERE lastName = 'Upston': 1
All documents: 2
Unindexed document self-link: dbs/kV5oAA==/colls/kV5oANHJPgE=/docs/kV5oANHJPgEBA
AAAAAAAAA==/
Novamente, a consulta retorna apenas um dos dois documentos, mas, desta vez, retorna Jane Doe, que solicitamos explicitamente para ser indexado. Mas, novamente como antes, a consulta sem uma cláusula WHERE recupera todos os documentos da coleção, incluindo o documento não indexado de Mark. Também podemos consultar o documento não indexado por seu ID, que o Banco de Dados de Documentos retorna, embora não esteja indexado.
Microsoft adicionou geospatial support, que permite armazenar dados de localização em seus documentos e realizar cálculos espaciais para distância e interseções entre pontos e polígonos.
Os dados espaciais descrevem a posição e a forma dos objetos no espaço.
Normalmente, pode ser usado para representar a localização de uma pessoa, um local de interesse ou os limites de uma cidade ou um lago.
Os casos de uso comuns geralmente envolvem consultas de proximidade. Por exemplo, "encontrar todas as universidades próximas à minha localização atual".
UMA Pointdenota uma única posição no espaço que representa a localização exata, por exemplo, o endereço de uma determinada universidade. Um ponto é representado no Banco de Dados de Documentos usando seu par de coordenadas (longitude e latitude). A seguir está um exemplo de ponto JSON.
{
"type":"Point",
"coordinates":[ 28.3, -10.7 ]
}
Vamos dar uma olhada em um exemplo simples que contém a localização de uma universidade.
{
"id":"case-university",
"name":"CASE: Center For Advanced Studies In Engineering",
"city":"Islamabad",
"location": {
"type":"Point",
"coordinates":[ 33.7194136, -73.0964862 ]
}
}
Para recuperar o nome da universidade com base na localização, você pode usar a seguinte consulta.
SELECT c.name FROM c
WHERE c.id = "case-university" AND ST_ISVALID({
"type":"Point",
"coordinates":[ 33.7194136, -73.0964862 ]})
Quando a consulta acima for executada, você receberá a seguinte saída.
[
{
"name": "CASE: Center For Advanced Studies In Engineering"
}
]
Criar documento com dados geoespaciais em .NET
Você pode criar um documento com dados geoespaciais, vamos dar uma olhada em um exemplo simples em que um documento universitário é criado.
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();
}
A seguir está a implementação para a classe 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; }
}
Quando o código acima for compilado e executado, você receberá a seguinte saída.
**** 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
Quando seu banco de dados começa a crescer além de 10 GB, você pode dimensionar simplesmente criando novas coleções e, em seguida, espalhando ou particionando seus dados em mais e mais coleções.
Mais cedo ou mais tarde, uma única coleção, com capacidade de 10 GB, não será suficiente para conter seu banco de dados. Agora, 10 GB pode não parecer um número muito grande, mas lembre-se de que estamos armazenando documentos JSON, que são apenas texto simples e você pode colocar muitos documentos de texto simples em 10 GB, mesmo considerando a sobrecarga de armazenamento para os índices.
O armazenamento não é a única preocupação quando se trata de escalabilidade. A taxa de transferência máxima disponível em uma coleção é 2,5 mil unidades de solicitação por segundo que você obtém com uma coleção S3. Portanto, se você precisar de uma taxa de transferência mais alta, também precisará escalar horizontalmente, particionando com várias coleções. O particionamento de expansão também é chamadohorizontal partitioning.
Existem muitas abordagens que podem ser usadas para particionar dados com o Azure DocumentDB. A seguir estão as estratégias mais comuns -
- Particionamento Spillover
- Particionamento de intervalo
- Particionamento de Pesquisa
- Particionamento Hash
Particionamento Spillover
O particionamento indireto é a estratégia mais simples porque não há chave de partição. Geralmente, é uma boa escolha começar quando você não tem certeza sobre muitas coisas. Você pode não saber se vai precisar escalar além de uma única coleção ou quantas coleções você pode precisar adicionar ou com que rapidez você pode precisar adicioná-las.
O particionamento spillover começa com uma única coleção e não há chave de partição.
A coleção começa a crescer e depois cresce um pouco mais, e então um pouco mais, até você começar a chegar perto do limite de 10 GB.
Ao atingir 90% da capacidade, você passa para uma nova coleção e começa a usá-la para novos documentos.
Depois que seu banco de dados escalar para um número maior de coleções, você provavelmente desejará mudar para uma estratégia baseada em uma chave de partição.
Ao fazer isso, você precisará reequilibrar seus dados movendo documentos para coleções diferentes com base em qualquer estratégia para a qual está migrando.
Particionamento de intervalo
Uma das estratégias mais comuns é o particionamento de intervalo. Com essa abordagem, você determina o intervalo de valores em que a chave de partição de um documento pode cair e direciona o documento para uma coleção correspondente a esse intervalo.
As datas são normalmente usadas com essa estratégia, quando você cria uma coleção para conter documentos que se enquadram no intervalo de datas definido. Quando você define intervalos pequenos o suficiente, onde você tem certeza de que nenhuma coleção excederá seu limite de 10 GB. Por exemplo, pode haver um cenário em que uma única coleção possa lidar razoavelmente com documentos de um mês inteiro.
Também pode ser o caso de a maioria dos usuários consultar dados atuais, que seriam dados deste mês ou talvez do mês passado, mas os usuários raramente procuram dados muito mais antigos. Então você começa em junho com uma coleção S3, que é a coleção mais cara que você pode comprar e oferece o melhor rendimento possível.
Em julho, você compra outra coleção S3 para armazenar os dados de julho e também reduz os dados de junho para uma coleção S2 menos cara. Então, em agosto, você obtém outra coleção S3 e escala julho até S2 e junho até S1. Vai, mês após mês, onde você sempre mantém os dados atuais disponíveis para alto rendimento e os dados mais antigos são mantidos disponíveis com rendimentos mais baixos.
Contanto que a consulta forneça uma chave de partição, apenas a coleção que precisa ser consultada será consultada e não todas as coleções no banco de dados como acontece com o particionamento de spillover.
Particionamento de Pesquisa
Com o particionamento de pesquisa, você pode definir um mapa de partição que roteia documentos para coleções específicas com base em sua chave de partição. Por exemplo, você pode particionar por região.
Armazene todos os documentos dos EUA em uma coleção, todos os documentos europeus em outra coleção e todos os documentos de qualquer outra região em uma terceira coleção.
Use este mapa de partição e um resolvedor de partição de pesquisa pode descobrir em qual coleção criar um documento e em quais coleções consultar, com base na chave de partição, que é a propriedade de região contida em cada documento.
Particionamento Hash
No particionamento de hash, as partições são atribuídas com base no valor de uma função de hash, permitindo distribuir uniformemente as solicitações e os dados em várias partições.
Isso é comumente usado para particionar dados produzidos ou consumidos de um grande número de clientes distintos e é útil para armazenar perfis de usuário, itens de catálogo, etc.
Vamos dar uma olhada em um exemplo simples de particionamento de intervalo usando o RangePartitionResolver fornecido pelo .NET SDK.
Step 1- Crie um novo DocumentClient e iremos criar duas coleções na tarefa CreateCollections. Um conterá documentos para usuários que têm IDs de usuário começando com A a M e o outro para IDs de usuário de N a 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 - Registre o resolvedor de intervalo para o banco de dados.
Step 3- Crie um novo RangePartitionResolver <string>, que é o tipo de dados de nossa chave de partição. O construtor usa dois parâmetros, o nome da propriedade da chave de partição e um dicionário que é o mapa de fragmentos ou mapa de partição, que é apenas uma lista dos intervalos e coleções correspondentes que estamos predefinindo para o resolvedor.
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;
}
É necessário codificar o maior valor UTF-8 possível aqui. Do contrário, o primeiro intervalo não corresponderia a nenhum Ms, exceto um único M, e da mesma forma para Z no segundo intervalo. Portanto, você pode apenas pensar neste valor codificado aqui como um caractere curinga para correspondência na chave de partição.
Step 4- Depois de criar o resolvedor, registre-o no banco de dados com o DocumentClient atual. Para fazer isso, basta atribuí-lo à propriedade de dicionário do PartitionResolver.
Criaremos e consultaremos documentos no banco de dados, não em uma coleção como você normalmente faz. O resolvedor usará esse mapa para encaminhar solicitações para as coleções apropriadas.
Agora vamos criar alguns documentos. Primeiro, criaremos um para userId Kirk e, em seguida, um para Spock.
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);
}
O primeiro parâmetro aqui é um auto-link para o banco de dados, não uma coleção específica. Isso não é possível sem um resolvedor de partição, mas com um ele funciona perfeitamente.
Ambos os documentos foram salvos no banco de dados myfirstdb, mas sabemos que Kirk está sendo armazenado na coleção de A a M e Spock está sendo armazenado na coleção de N a Z, se nosso RangePartitionResolver estiver funcionando corretamente.
Vamos chamá-los da tarefa CreateDocumentClient, conforme mostrado no código a seguir.
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);
}
}
Quando o código acima for executado, você receberá a seguinte saída.
**** Create Documents Across Partitions ****
Document 1: dbs/Ic8LAA==/colls/Ic8LAO2DxAA=/docs/Ic8LAO2DxAABAAAAAAAAAA==/
Document 2: dbs/Ic8LAA==/colls/Ic8LAP12QAE=/docs/Ic8LAP12QAEBAAAAAAAAAA==/
Como visto, os self-links dos dois documentos têm IDs de recursos diferentes porque existem em duas coleções separadas.
Com a ferramenta DocumentDB Data Migration, você pode facilmente migrar dados para DocumentDB. A ferramenta DocumentDB Data Migration é um utilitário gratuito e de código aberto que você pode baixar no Centro de Download da Microsofthttps://www.microsoft.com/
A ferramenta de migração suporta muitas fontes de dados, algumas delas estão listadas abaixo -
- servidor SQL
- Arquivos JSON
- Arquivos simples de valores separados por vírgula (CSV)
- MongoDB
- Armazenamento de Tabela Azure
- Amazon DynamoDB
- HBase e até mesmo outros bancos de dados DocumentDB
Depois de fazer download da ferramenta de migração de dados do DocumentDB, extraia o arquivo zip.
Você pode ver dois executáveis nesta pasta, conforme mostrado na imagem a seguir.
Primeiro, há dt.exe, que é a versão do console com uma interface de linha de comando, e depois há dtui.exe, que é a versão desktop com uma interface gráfica do usuário.
Vamos lançar a versão GUI.
Você pode ver a página de boas-vindas. Clique em 'Avançar' para a página de informações da fonte.
É aqui que você configura sua fonte de dados e pode ver as muitas opções com suporte no menu suspenso.
Quando você faz uma seleção, o resto da página Informações da fonte muda de acordo.
É muito fácil importar dados para o DocumentDB usando a ferramenta de migração de dados do DocumentDB. Recomendamos que você exercite os exemplos acima e use os outros arquivos de dados também.
DocumentDB fornece os conceitos para controlar o acesso aos recursos do DocumentDB. O acesso aos recursos do Banco de Dados de Documentos é controlado por um token de chave mestra ou um token de recurso. As conexões baseadas em tokens de recursos podem acessar apenas os recursos especificados pelos tokens e nenhum outro recurso. Os tokens de recursos são baseados nas permissões do usuário.
Primeiro, você cria um ou mais usuários, e eles são definidos no nível do banco de dados.
Em seguida, você cria uma ou mais permissões para cada usuário, com base nos recursos que deseja permitir que cada usuário acesse.
Cada permissão gera um token de recurso que permite acesso somente leitura ou total a um determinado recurso e que pode ser qualquer recurso de usuário no banco de dados.
Os usuários são definidos no nível do banco de dados e as permissões são definidas para cada usuário.
Usuários e permissões se aplicam a todas as coleções no banco de dados.
Vamos dar uma olhada em um exemplo simples no qual aprenderemos como definir usuários e permissões para obter segurança granular no Banco de Dados de Documentos.
Começaremos com um novo DocumentClient e consultaremos o banco de dados 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");
}
}
A seguir está a implementação de 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- Crie dois usuários, Alice e Tom como qualquer recurso que criarmos, construímos um objeto de definição com o Id desejado e chamamos o método de criação e, neste caso, estamos chamando CreateUserAsync com o SelfLink do banco de dados e o userDefinition. Recebemos o resultado de cuja propriedade de recurso obtemos o objeto de usuário recém-criado.
Agora, para ver esses dois novos usuários no banco de dados.
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- Chame CreateUserQuery, no UsersLink do banco de dados para recuperar uma lista de todos os usuários. Em seguida, percorra-os e visualize suas propriedades.
Agora temos que criá-los primeiro. Então, digamos que quiséssemos permitir a Alice permissões de leitura / gravação para a coleção MyCollection, mas Tom só pode ler documentos na coleção.
await CreatePermission(client, alice, "Alice Collection Access", PermissionMode.All,
collection);
await CreatePermission(client, tom, "Tom Collection Access", PermissionMode.Read,
collection);
Step 3- Crie uma permissão em um recurso que seja coleção MyCollection, portanto, precisamos obter um SelfLink para esse recurso.
Step 4 - Em seguida, crie um Permission.All nesta coleção para Alice e um Permission.Read nesta coleção para Tom.
A seguir está a implementação de 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);
}
Como você já deve esperar, fazemos isso criando um objeto de definição para a nova permissão, que inclui um Id e um permissionMode, que é Permission.All ou Permission.Read, e o SelfLink do recurso que está sendo protegido pela permissão.
Step 5 - Chame CreatePermissionAsync e obtenha a permissão criada da propriedade do recurso no resultado.
Para visualizar a permissão criada, a seguir está a implementação de 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);
}
Desta vez, é uma consulta de permissão no link de permissões do usuário e simplesmente listamos cada permissão retornada para o usuário.
Vamos deletar as permissões de Alice e Tom.
await DeletePermission(client, alice, "Alice Collection Access");
await DeletePermission(client, tom, "Tom Collection Access");
A seguir está a implementação de 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 - Para excluir permissões, consulte por ID de permissão para obter o SelfLink e, em seguida, use o SelfLink para excluir a permissão.
A seguir, vamos excluir os próprios usuários. Vamos deletar ambos os usuários.
await DeleteUser(client, "Alice");
await DeleteUser(client, "Tom");
A seguir está a implementação de 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 - Primeiro consulte para obter seu SelfLink e, em seguida, chame DeleteUserAsync para excluir seu objeto de usuário.
A seguir está a implementação da tarefa CreateDocumentClient na qual chamamos todas as tarefas acima.
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");
}
}
Quando o código acima for compilado e executado, você receberá a seguinte saída.
**** 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
Neste capítulo, aprenderemos como visualizar dados armazenados no Banco de Dados de Documentos. A Microsoft forneceu a ferramenta Power BI Desktop que transforma seus dados em visuais ricos. Ele também permite que você recupere dados de várias fontes de dados, mescle e transforme os dados, crie relatórios e visualizações poderosos e publique os relatórios no Power BI.
Na versão mais recente do Power BI Desktop, a Microsoft adicionou suporte para DocumentDB também, no qual você agora pode se conectar à sua conta DocumentDB. Você pode baixar essa ferramenta no link,https://powerbi.microsoft.com
Vamos dar uma olhada em um exemplo no qual visualizaremos os dados de terremotos importados no último capítulo.
Step 1 - Depois que a ferramenta for baixada, inicie a área de trabalho do Power BI.
Step 2 - Clique na opção 'Get Data' que está na guia Home no grupo External Data e irá exibir a página Get Data.
Step 3 - Selecione a opção Microsoft Azure DocumentDB (Beta) e clique no botão 'Conectar'.
Step 4 - Insira a URL de sua conta do Azure DocumentDB, Banco de Dados e Coleção da qual deseja visualizar os dados e pressione OK.
Se você estiver se conectando a este terminal pela primeira vez, será solicitada a chave da conta.
Step 5 - Insira a chave da conta (chave primária) que é exclusiva para cada conta do Banco de Dados de Documentos disponível no portal do Azure e clique em Conectar.
Quando a conta for conectada com êxito, ele recuperará os dados do banco de dados especificado. O painel Visualização mostra uma lista de itens de registro, um documento é representado como um tipo de registro no Power BI.
Step 6 - Clique no botão 'Editar' para iniciar o Editor de Consultas.
Step 7 - No Editor de Consultas do Power BI, você deve ver uma coluna Documento no painel central, clique no expansor no lado direito do cabeçalho da coluna Documento e selecione as colunas que deseja exibir.
Como você pode ver, temos a latitude e a longitude como colunas separadas, mas visualizamos os dados na forma de coordenadas de latitude e longitude.
Step 8 - Para fazer isso, clique na guia 'Adicionar coluna'.
Step 9 - Selecione Adicionar coluna personalizada que exibirá a página a seguir.
Step 10- Especifique o novo nome da coluna, digamos LatLong e também a fórmula que combinará a latitude e longitude em uma coluna separada por uma vírgula. A seguir está a fórmula.
Text.From([latitude])&", "&Text.From([longitude])
Step 11 - Clique em OK para continuar e você verá que a nova coluna foi adicionada.
Step 12 - Vá para a guia Página inicial e clique na opção 'Fechar e aplicar'.
Step 13- Você pode criar relatórios arrastando e soltando campos na tela Relatório. Você pode ver à direita, há dois painéis - um painel Visualizações e o outro é o painel Campos.
Vamos criar uma visualização do mapa mostrando a localização de cada terremoto.
Step 14 - Arraste o tipo visual do mapa do painel Visualizações.
Step 15- Agora, arraste e solte o campo LatLong do painel Campos para a propriedade Local no painel Visualizações. Em seguida, arraste e solte o campo de magnitude na propriedade Values.
Step 16 - Arraste e solte o campo de profundidade na propriedade Saturação de cor.
Agora você verá o visual do mapa mostrando um conjunto de bolhas indicando a localização de cada terremoto.