DocumentDB - szybki przewodnik
W tym rozdziale omówimy pokrótce główne koncepcje dotyczące NoSQL i baz danych dokumentów. Będziemy również mieć szybki przegląd DocumentDB.
Baza danych dokumentów NoSQL
DocumentDB to najnowsza baza danych dokumentów NoSQL firmy Microsoft, więc kiedy mówisz o bazie danych dokumentów NoSQL, co dokładnie rozumiemy przez NoSQL i bazę danych dokumentów?
SQL oznacza Structured Query Language, który jest tradycyjnym językiem zapytań relacyjnych baz danych. SQL jest często utożsamiany z relacyjnymi bazami danych.
Naprawdę bardziej pomocne jest myślenie o bazie danych NoSQL jako o nierelacyjnej bazie danych, więc NoSQL naprawdę oznacza nierelacyjną.
Istnieją różne typy baz danych NoSQL, które obejmują magazyny wartości kluczy, takie jak -
- Magazyn tabel Azure.
- Sklepy oparte na kolumnach, takie jak Cassandra.
- Grafowe bazy danych, takie jak NEO4.
- Bazy danych dokumentów, takie jak MongoDB i Azure DocumentDB.
Azure DocumentDB
Microsoft oficjalnie uruchomił Azure DocumentDB 8 kwietnia th , 2015, i to z pewnością można scharakteryzować jako typowy bazy dokumentów NoSQL. Jest ogromnie skalowalny i działa z dokumentami JSON bez schematu.
DocumentDB to prawdziwie wolna od schematów usługa bazy danych dokumentów NoSQL zaprojektowana dla nowoczesnych aplikacji mobilnych i internetowych.
Zapewnia również konsekwentnie szybkie odczyty i zapisy, elastyczność schematów i możliwość łatwego skalowania bazy danych w górę iw dół na żądanie.
Nie zakłada ani nie wymaga żadnego schematu dla indeksowanych dokumentów JSON.
DocumentDB automatycznie indeksuje każdą właściwość w dokumencie, gdy tylko dokument zostanie dodany do bazy danych.
DocumentDB umożliwia złożone zapytania ad-hoc przy użyciu języka SQL, a zapytania dotyczące każdego dokumentu są natychmiastowo dostępne w momencie jego utworzenia, a ponadto można wyszukiwać według dowolnej właściwości w dowolnym miejscu w hierarchii dokumentów.
DocumentDB - cennik
Usługa DocumentDB jest rozliczana na podstawie liczby kolekcji znajdujących się na koncie bazy danych. Każde konto może mieć jedną lub więcej baz danych, a każda baza danych może mieć praktycznie nieograniczoną liczbę kolekcji, chociaż początkowy przydział domyślny wynosi 100. Ten przydział można znieść, kontaktując się z pomocą techniczną platformy Azure.
Kolekcja to nie tylko jednostka skali, ale także jednostka kosztu, więc w DocumentDB płacisz za kolekcję, która ma pojemność do 10 GB.
Będziesz potrzebować co najmniej jednej kolekcji S1 do przechowywania dokumentów w bazie danych, która będzie kosztować około 25 USD miesięcznie i będzie rozliczana w ramach subskrypcji platformy Azure.
W miarę powiększania się bazy danych i przekraczania 10 GB, musisz kupić kolejną kolekcję, aby przechowywać dodatkowe dane.
Każda kolekcja S1 zapewni 250 jednostek żądań na sekundę, a jeśli to nie wystarczy, możesz przeskalować kolekcję do S2 i uzyskać 1000 jednostek żądań na sekundę za około 50 USD miesięcznie.
Możesz także zamienić go na S3 i płacić około 100 USD miesięcznie.
DocumentDB wyróżnia się kilkoma bardzo wyjątkowymi możliwościami. Azure DocumentDB oferuje następujące kluczowe możliwości i korzyści.
Schema Free
W relacyjnej bazie danych każda tabela ma schemat definiujący kolumny i typy danych, z którymi musi być zgodny każdy wiersz tabeli.
W przeciwieństwie do tego baza danych dokumentów nie ma zdefiniowanego schematu, a każdy dokument może mieć inną strukturę.
Składnia SQL
DocumentDB umożliwia tworzenie złożonych zapytań ad-hoc przy użyciu języka SQL, a zapytania dotyczące każdego dokumentu są natychmiastowo dostępne w momencie jego utworzenia. Możesz wyszukiwać według dowolnej właściwości w dowolnym miejscu w hierarchii dokumentów.
Dostrajalna spójność
Zapewnia pewne szczegółowe, dobrze zdefiniowane poziomy spójności, co pozwala na rozsądne kompromisy między spójnością, dostępnością i opóźnieniem.
Możesz wybrać jeden z czterech dobrze zdefiniowanych poziomów spójności, aby uzyskać optymalny kompromis między spójnością a wydajnością. W przypadku zapytań i operacji odczytu DocumentDB oferuje cztery różne poziomy spójności -
- Strong
- Bounded-staleness
- Session
- Eventual
Elastyczna skala
Skalowalność to nazwa gry z NoSQL, a DocumentDB zapewnia. DocumentDB dowiodła już swojej skali.
Główne usługi, takie jak Office OneNote i Xbox, są już obsługiwane przez DocumentDB z bazami danych zawierającymi dziesiątki terabajtów dokumentów JSON, ponad milion aktywnych użytkowników i działającymi konsekwentnie z 99,95% dostępnością.
Możesz elastycznie skalować DocumentDB z przewidywalną wydajnością, tworząc więcej jednostek w miarę rozwoju aplikacji.
W pełni zarządzany
DocumentDB jest dostępna jako w pełni zarządzana platforma chmurowa jako usługa działająca na platformie Azure.
Po prostu nie ma nic do zainstalowania lub zarządzania.
Nie ma serwerów, kabli, systemów operacyjnych ani aktualizacji, z którymi można by sobie poradzić, ani replik do skonfigurowania.
Firma Microsoft wykonuje całą tę pracę i utrzymuje działanie usługi.
W ciągu dosłownie minut możesz rozpocząć pracę z usługą DocumentDB, używając tylko przeglądarki i subskrypcji platformy Azure.
Firma Microsoft udostępnia bezpłatną wersję programu Visual Studio, która zawiera również SQL Server i można ją pobrać z witryny https://www.visualstudio.com
Instalacja
Step 1- Po zakończeniu pobierania uruchom instalator. Zostanie wyświetlone następujące okno dialogowe.
Step 2 - Kliknij przycisk Instaluj, aby rozpocząć proces instalacji.
Step 3 - Po pomyślnym zakończeniu procesu instalacji zostanie wyświetlone następujące okno dialogowe.
Step 4 - Zamknij to okno dialogowe iw razie potrzeby uruchom ponownie komputer.
Step 5- Teraz otwórz Visual studio z menu Start, które otworzy poniższe okno dialogowe. Po raz pierwszy zajmie to trochę czasu tylko na przygotowanie.
Gdy wszystko będzie gotowe, zobaczysz główne okno programu Visual Studio.
Step 6 - Stwórzmy nowy projekt z Plik → Nowy → Projekt.
Step 7 - Wybierz aplikację konsoli, wprowadź DocumentDBDemo w polu Nazwa i kliknij przycisk OK.
Step 8 - W Eksploratorze rozwiązań kliknij projekt prawym przyciskiem myszy.
Step 9 - Wybierz opcję Zarządzaj pakietami NuGet, co spowoduje otwarcie następującego okna w programie Visual Studio i w polu wprowadzania wyszukiwania w trybie online wyszukaj bibliotekę klienta usługi DocumentDB.
Step 10 - Zainstaluj najnowszą wersję, klikając przycisk instalacji.
Step 11- Kliknij „Akceptuję”. Po zakończeniu instalacji zobaczysz komunikat w oknie wyjściowym.
Teraz możesz rozpocząć swoją aplikację.
Aby korzystać z Microsoft Azure DocumentDB, musisz utworzyć konto DocumentDB. W tym rozdziale utworzymy konto DocumentDB za pomocą Azure Portal.
Step 1 - Zaloguj się do sieci https://portal.azure.com jeśli masz już subskrypcję platformy Azure, w przeciwnym razie musisz się najpierw zalogować.
Zobaczysz główny pulpit nawigacyjny. Jest w pełni konfigurowalny, więc możesz układać te kafelki w dowolny sposób, zmieniać ich rozmiar, dodawać i usuwać kafelki do rzeczy, których często używasz lub których już nie robisz.
Step 2 - Wybierz opcję „Nowy” w lewej górnej części strony.
Step 3 - Teraz wybierz opcję Data + Storage> Azure DocumentDB i zobaczysz następującą sekcję konta New DocumentDB.
Musimy wymyślić globalnie unikalną nazwę (identyfikator), która w połączeniu z .documents.azure.com jest publicznie adresowanym punktem końcowym naszego konta DocumentDB. Wszystkie bazy danych, które tworzymy pod tym kontem, są dostępne przez Internet za pomocą tego punktu końcowego.
Step 4 - Nazwijmy to azuredocdbdemo i kliknij Resource Group → new_resource.
Step 5- Wybierz lokalizację, tj. W którym centrum danych Microsoft ma być hostowane to konto. Wybierz lokalizację i wybierz swój region.
Step 6 - Zaznacz pole wyboru Przypnij do pulpitu nawigacyjnego i po prostu kliknij przycisk Utwórz.
Możesz zobaczyć, że kafelek został już dodany do pulpitu nawigacyjnego i informuje nas, że konto jest tworzone. Skonfigurowanie nowego konta może zająć kilka minut, podczas gdy DocumentDB przydziela punkt końcowy, rezerwuje repliki i wykonuje inne prace w tle.
Po zakończeniu zobaczysz pulpit nawigacyjny.
Step 7 - Teraz kliknij utworzone konto DocumentDB, a zobaczysz szczegółowy ekran, jak na poniższym obrazku.
Kiedy zaczynasz programować w DocumentDB, pierwszym krokiem jest połączenie. Aby połączyć się z kontem DocumentDB, będziesz potrzebować dwóch rzeczy;
- Endpoint
- Klucz autoryzacyjny
Punkt końcowy
Punkt końcowy to adres URL do konta usługi DocumentDB, który jest tworzony przez połączenie nazwy konta usługi DocumentDB z .documents.azure.com. Przejdźmy do pulpitu nawigacyjnego.
Teraz kliknij utworzone konto DocumentDB. Zobaczysz szczegóły, jak pokazano na poniższym obrazku.
Po wybraniu opcji „Klucze” wyświetlą się dodatkowe informacje, jak pokazano na poniższym obrazku. Zobaczysz również adres URL do konta DocumentDB, którego możesz użyć jako punktu końcowego.
Klucz autoryzacyjny
Klucz autoryzacyjny zawiera Twoje poświadczenia i są dwa rodzaje kluczy. Klucz główny umożliwia pełny dostęp do wszystkich zasobów na koncie, a tokeny zasobów umożliwiają ograniczony dostęp do określonych zasobów.
Klucze główne
Nie ma nic, czego nie można zrobić za pomocą klucza głównego. Jeśli chcesz, możesz zdmuchnąć całą bazę danych, używając klucza głównego.
Z tego powodu zdecydowanie nie chcesz udostępniać klucza głównego ani dystrybuować go do środowisk klienckich. Jako dodatkowy środek bezpieczeństwa warto często go zmieniać.
W rzeczywistości istnieją dwa klucze główne dla każdego konta bazy danych, podstawowy i pomocniczy, jak zaznaczono na powyższym zrzucie ekranu.
Żetony zasobów
Możesz również użyć tokenów zasobów zamiast klucza głównego.
Połączenia oparte na tokenach zasobów mogą uzyskiwać dostęp tylko do zasobów określonych przez tokeny, a nie do innych zasobów.
Tokeny zasobów są oparte na uprawnieniach użytkowników, więc najpierw należy utworzyć co najmniej jednego użytkownika, który jest definiowany na poziomie bazy danych.
Tworzysz jedno lub więcej uprawnień dla każdego użytkownika na podstawie zasobów, do których chcesz zezwolić każdemu użytkownikowi.
Każde uprawnienie generuje token zasobu, który umożliwia dostęp tylko do odczytu lub pełny dostęp do danego zasobu i może to być dowolny zasób użytkownika w bazie danych.
Przejdźmy do aplikacji konsolowej stworzonej w rozdziale 3.
Step 1 - Dodaj następujące odniesienia w pliku Program.cs.
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;
Step 2- Teraz dodaj adres URL punktu końcowego i klucz autoryzacji. W tym przykładzie będziemy używać klucza podstawowego jako klucza autoryzacyjnego.
Zwróć uwagę, że w Twoim przypadku adres URL punktu końcowego i klucz autoryzacji powinny być różne.
private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
private const string AuthorizationKey =
"BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
Step 3 - Utwórz nowe wystąpienie DocumentClient w zadaniu asynchronicznym o nazwie CreateDocumentClient i utwórz wystąpienie nowego DocumentClient.
Step 4 - Wywołaj zadanie asynchroniczne z metody Main.
Poniżej znajduje się jak dotąd kompletny plik Program.cs.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;
namespace DocumentDBDemo {
class Program {
private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
private const string AuthorizationKey = "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/
StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
static void Main(string[] args) {
try {
CreateDocumentClient().Wait();
} catch (Exception e) {
Exception baseException = e.GetBaseException();
Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
}
Console.ReadKey();
}
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey);
}
}
}
W tym rozdziale nauczyliśmy się, jak połączyć się z kontem DocumentDB i utworzyć instancję klasy DocumentClient.
W tym rozdziale nauczymy się, jak stworzyć bazę danych. Aby korzystać z Microsoft Azure DocumentDB, musisz mieć konto DocumentDB, bazę danych, kolekcję i dokumenty. Mamy już konto DocumentDB, teraz aby stworzyć bazę danych mamy dwie opcje -
- Witryna Microsoft Azure Portal lub
- .NET SDK
Utwórz bazę danych dla DocumentDB przy użyciu portalu Microsoft Azure
Aby utworzyć bazę danych za pomocą portalu, wykonaj następujące kroki.
Step 1 - Zaloguj się do Azure Portal, a zobaczysz pulpit nawigacyjny.
Step 2 - Teraz kliknij utworzone konto DocumentDB, a zobaczysz szczegóły, jak pokazano na poniższym zrzucie ekranu.
Step 3 - Wybierz opcję Dodaj bazę danych i podaj identyfikator swojej bazy danych.
Step 4 - Kliknij OK.
Widać, że baza danych została dodana. W tej chwili nie ma kolekcji, ale możemy dodać kolekcje później, które są kontenerami, w których będą przechowywane nasze dokumenty JSON. Zwróć uwagę, że ma zarówno identyfikator, jak i identyfikator zasobu.
Utwórz bazę danych dla DocumentDB przy użyciu .Net SDK
Aby utworzyć bazę danych za pomocą .Net SDK, wykonaj następujące kroki.
Step 1 - Otwórz aplikację konsolową w programie Visual Studio z poprzedniego rozdziału.
Step 2- Utwórz nową bazę danych, tworząc nowy obiekt bazy danych. Aby utworzyć nową bazę danych, musimy tylko przypisać właściwość Id, którą ustawiamy na „mynewdb” w zadaniu 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- Teraz przekaż tę bazę danych databaseDefinition do CreateDatabaseAsync i uzyskaj wynik z właściwością Resource. Wszystkie metody obiektu create zwracają właściwość Resource, która opisuje utworzony element, którym w tym przypadku jest baza danych.
Otrzymujemy nowy obiekt bazy danych z właściwości Resource i jest on wyświetlany na konsoli wraz z identyfikatorem zasobu przypisanym do niego przez DocumentDB.
Step 4 - Teraz wywołaj zadanie CreateDatabase z zadania CreateDocumentClient po utworzeniu wystąpienia DocumentClient.
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
await CreateDatabase(client);
}
Poniżej znajduje się jak dotąd kompletny plik Program.cs.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;
namespace DocumentDBDemo {
class Program {
private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
private const string AuthorizationKey = "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/
StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
static void Main(string[] args) {
try {
CreateDocumentClient().Wait();
} catch (Exception e) {
Exception baseException = e.GetBaseException();
Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
}
Console.ReadKey();
}
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
await CreateDatabase(client);
}
}
private async static Task CreateDatabase(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("******** Create Database *******");
var databaseDefinition = new Database { Id = "mynewdb" };
var result = await client.CreateDatabaseAsync(databaseDefinition);
var database = result.Resource;
Console.WriteLine(" Database Id: {0}; Rid: {1}", database.Id, database.ResourceId);
Console.WriteLine("******** Database Created *******");
}
}
}
Gdy powyższy kod zostanie skompilowany i wykonany, otrzymasz następujące dane wyjściowe zawierające identyfikatory bazy danych i zasobów.
******** Create Database *******
Database Id: mynewdb; Rid: ltpJAA==
******** Database Created *******
Do tej pory utworzyliśmy dwie bazy danych na naszym koncie DocumentDB, pierwsza jest tworzona za pomocą Azure Portal, a druga za pomocą .Net SDK. Teraz, aby wyświetlić te bazy danych, możesz użyć Azure Portal.
Przejdź do konta usługi DocumentDB w witrynie Azure Portal, a zobaczysz teraz dwie bazy danych.
Możesz również przeglądać lub wyświetlać bazy danych z kodu za pomocą .Net SDK. Poniżej przedstawiono wymagane kroki.
Step 1 - Wyślij zapytanie do bazy danych bez parametrów, które zwróci pełną listę, ale możesz również przekazać zapytanie w celu wyszukania określonej bazy danych lub określonych baz danych.
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);
}
Zobaczysz, że istnieje kilka metod CreateQuery do lokalizowania kolekcji, dokumentów, użytkowników i innych zasobów. Te metody w rzeczywistości nie wykonują zapytania, po prostu definiują zapytanie i zwracają iterowalny obiekt.
To wywołanie ToList () faktycznie wykonuje zapytanie, iteruje wyniki i zwraca je w postaci listy.
Step 2 - Wywołaj metodę GetDatabases z zadania CreateDocumentClient po utworzeniu wystąpienia DocumentClient.
Step 3 - Musisz także skomentować zadanie CreateDatabase lub zmienić identyfikator bazy danych, w przeciwnym razie zostanie wyświetlony komunikat o błędzie, że baza danych istnieje.
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
//await CreateDatabase(client);
GetDatabases(client);
}
Poniżej znajduje się jak dotąd kompletny plik Program.cs.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;
namespace DocumentDBDemo {
class Program {
private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
private const string AuthorizationKey = "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/
StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
static void Main(string[] args) {
try {
CreateDocumentClient().Wait();
} catch (Exception e) {
Exception baseException = e.GetBaseException();
Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
}
Console.ReadKey();
}
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
await CreateDatabase(client);
GetDatabases(client);
}
}
private async static Task CreateDatabase(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("******** Create Database *******");
var databaseDefinition = new Database { Id = "mynewdb" };
var result = await client.CreateDatabaseAsync(databaseDefinition);
var database = result.Resource;
Console.WriteLine(" Database Id: {0}; Rid: {1}", database.Id, database.ResourceId);
Console.WriteLine("******** Database Created *******");
}
private static void GetDatabases(DocumentClient client) {
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("******** Get Databases List ********");
var databases = client.CreateDatabaseQuery().ToList();
foreach (var database in databases) {
Console.WriteLine(" Database Id: {0}; Rid: {1}",
database.Id, database.ResourceId);
}
Console.WriteLine();
Console.WriteLine("Total databases: {0}", databases.Count);
}
}
}
Kiedy powyższy kod zostanie skompilowany i wykonany, otrzymasz następujące dane wyjściowe, które zawierają identyfikatory bazy danych i zasobów obu baz danych. Na końcu zobaczysz również całkowitą liczbę baz danych.
******** Get Databases List ********
Database Id: myfirstdb; Rid: Ic8LAA==
Database Id: mynewdb; Rid: ltpJAA==
Total databases: 2
Bazę danych lub bazy danych można usunąć z portalu, a także z kodu za pomocą .Net SDK. Tutaj omówimy krok po kroku, jak upuścić bazę danych w DocumentDB.
Step 1- Przejdź do swojego konta DocumentDB w witrynie Azure Portal. Do celów demonstracyjnych dodałem jeszcze dwie bazy danych, jak widać na poniższym zrzucie ekranu.
Step 2- Aby usunąć dowolną bazę danych, musisz ją kliknąć. Wybierzmy tempdb, zobaczysz następującą stronę, wybierz opcję „Usuń bazę danych”.
Step 3 - Wyświetli się komunikat potwierdzający, teraz kliknij przycisk „Tak”.
Zobaczysz, że baza danych tempdb nie jest już dostępna na pulpicie nawigacyjnym.
Możesz również usunąć bazy danych z kodu za pomocą .Net SDK. Aby wykonać następujące czynności.
Step 1 - Usuńmy bazę danych, podając identyfikator bazy danych, którą chcemy usunąć, ale potrzebujemy jej SelfLink.
Step 2 - Wywołujemy CreateDatabaseQuery jak poprzednio, ale tym razem faktycznie dostarczamy zapytanie, aby zwrócić tylko jedną bazę danych o identyfikatorze 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- Tym razem możemy wywołać AsEnumerable zamiast ToList (), ponieważ tak naprawdę nie potrzebujemy obiektu listy. Oczekując tylko wyniku, wywołanie AsEnumerable jest wystarczające, abyśmy mogli pobrać pierwszy obiekt bazy danych zwrócony przez zapytanie z First (). To jest obiekt bazy danych dla tempdb1 i ma SelfLink, którego możemy użyć do wywołania DeleteDatabaseAsync, który usuwa bazę danych.
Step 4 - Należy również wywołać zadanie DeleteDatabase z zadania CreateDocumentClient po utworzeniu wystąpienia DocumentClient.
Step 5 - Aby wyświetlić listę baz danych po usunięciu określonej bazy danych, ponownie wywołajmy metodę GetDatabases.
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
//await CreateDatabase(client);
GetDatabases(client);
await DeleteDatabase(client);
GetDatabases(client);
}
Poniżej znajduje się jak dotąd kompletny plik Program.cs.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;
namespace DocumentDBDemo {
class Program {
private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
private const string AuthorizationKey = "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/
StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
static void Main(string[] args) {
try {
CreateDocumentClient().Wait();
} catch (Exception e) {
Exception baseException = e.GetBaseException();
Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
}
Console.ReadKey();
}
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
//await CreateDatabase(client);
GetDatabases(client);
await DeleteDatabase(client);
GetDatabases(client);
}
}
private async static Task CreateDatabase(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("******** Create Database *******");
var databaseDefinition = new Database { Id = "mynewdb" };
var result = await client.CreateDatabaseAsync(databaseDefinition);
var database = result.Resource;
Console.WriteLine(" Database Id: {0}; Rid: {1}",
database.Id, database.ResourceId);
Console.WriteLine("******** Database Created *******");
}
private static void GetDatabases(DocumentClient client) {
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("******** Get Databases List ********");
var databases = client.CreateDatabaseQuery().ToList();
foreach (var database in databases) {
Console.WriteLine(" Database Id: {0}; Rid: {1}", database.Id,
database.ResourceId);
}
Console.WriteLine();
Console.WriteLine("Total databases: {0}", databases.Count);
}
private async static Task DeleteDatabase(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("******** Delete Database ********");
Database database = client
.CreateDatabaseQuery("SELECT * FROM c WHERE c.id = 'tempdb1'")
.AsEnumerable()
.First();
await client.DeleteDatabaseAsync(database.SelfLink);
}
}
}
Kiedy powyższy kod zostanie skompilowany i wykonany, otrzymasz następujące dane wyjściowe, które zawierają identyfikatory bazy danych i zasobów trzech baz danych oraz całkowitą liczbę baz danych.
******** 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
Po usunięciu bazy danych zobaczysz również na końcu, że na koncie DocumentDB pozostały tylko dwie bazy danych.
W tym rozdziale nauczymy się, jak tworzyć kolekcje. Jest to podobne do tworzenia bazy danych. Możesz utworzyć kolekcję z portalu lub z kodu przy użyciu .Net SDK.
Step 1 - Przejdź do głównego pulpitu nawigacyjnego w witrynie Azure Portal.
Step 2 - Wybierz myfirstdb z listy baz danych.
Step 3- Kliknij opcję „Dodaj kolekcję” i określ identyfikator kolekcji. Wybierz poziom cenowy dla innej opcji.
Step 4 - Wybierzmy S1 Standard i kliknij przycisk Wybierz → OK.
Jak widać, MyCollection jest dodawane do myfirstdb.
Możesz również utworzyć kolekcję na podstawie kodu za pomocą .Net SDK. Rzućmy okiem na poniższe kroki, aby dodać kolekcje z kodu.
Step 1 - Otwórz aplikację konsoli w programie Visual Studio.
Step 2 - Aby utworzyć kolekcję, najpierw pobierz bazę danych myfirstdb według jej identyfikatora w zadaniu 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");
}
}
Poniżej przedstawiono implementację zadania 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);
}
Tworzymy nowy obiekt DocumentCollection, który definiuje nową kolekcję z żądanym identyfikatorem dla metody CreateDocumentCollectionAsync, która również akceptuje parametr options, którego używamy tutaj do ustawiania warstwy wydajności nowej kolekcji, którą nazywamy offerType.
Domyślnie jest to S1, a ponieważ nie przekazaliśmy w offerType dla MyCollection1, więc będzie to kolekcja S1, a dla MyCollection2 przekazaliśmy S2, co sprawia, że jest to S2, jak pokazano powyżej.
Poniżej przedstawiono implementację metody 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);
}
Poniżej znajduje się pełna implementacja pliku program.cs dla kolekcji.
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);
}
}
}
Kiedy powyższy kod zostanie skompilowany i wykonany, otrzymasz następujące dane wyjściowe, które zawierają wszystkie informacje związane z kolekcją.
**** 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
Aby usunąć kolekcję lub kolekcje, możesz zrobić to samo z portalu, a także z kodu za pomocą .Net SDK.
Step 1- Przejdź do swojego konta DocumentDB w witrynie Azure Portal. Do celów demonstracyjnych dodałem jeszcze dwie kolekcje, jak widać na poniższym zrzucie ekranu.
Step 2- Aby usunąć dowolną kolekcję, musisz ją kliknąć. Wybierzmy TempCollection1. Zobaczysz następującą stronę, wybierz opcję „Usuń kolekcję”.
Step 3- Wyświetli komunikat potwierdzający. Teraz kliknij przycisk „Tak”.
Zobaczysz, że kolekcja TempCollection1 nie jest już dostępna na pulpicie nawigacyjnym.
Możesz także usunąć kolekcje ze swojego kodu za pomocą .Net SDK. Aby to zrobić, wykonaj następujące kroki.
Step 1 - Usuńmy kolekcję, podając identyfikator kolekcji, którą chcemy usunąć.
Jest to typowy wzorzec odpytywania przez Id w celu uzyskania selfLinks potrzebnych do usunięcia zasobu.
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);
}
Tutaj widzimy preferowany sposób konstruowania sparametryzowanego zapytania. Nie kodujemy na stałe elementu collectionId, więc ta metoda może służyć do usuwania dowolnej kolekcji. Pytamy o określoną kolekcję według Id, w której parametr Id jest zdefiniowany w tym SqlParameterCollection przypisanym do właściwości parametru tego SqlQuerySpec.
Następnie zestaw SDK konstruuje ostateczny ciąg zapytania dla bazy danych DocumentDB z osadzonym w nim identyfikatorem collectionId.
Step 2 - Uruchom zapytanie, a następnie użyj jego SelfLink, aby usunąć kolekcję z zadania 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");
}
}
Poniżej znajduje się pełna implementacja pliku 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);
}
}
}
Gdy powyższy kod zostanie skompilowany i wykonany, otrzymasz następujące dane wyjściowe.
**** Delete Collection TempCollection in myfirstdb ****
Deleted collection TempCollection from database myfirstdb
W tym rozdziale zajmiemy się rzeczywistymi dokumentami w kolekcji. Możesz tworzyć dokumenty za pomocą Azure Portal lub .Net SDK.
Tworzenie dokumentów za pomocą portalu Azure
Przyjrzyjmy się poniższym krokom, aby dodać dokument do Twojej kolekcji.
Step 1 - Dodaj nową kolekcję Rodziny warstw cenowych S1 w myfirstdb.
Step 2 - Wybierz kolekcję Rodziny i kliknij opcję Utwórz dokument, aby otworzyć blok Nowy dokument.
To tylko prosty edytor tekstu, który pozwala wpisać dowolny kod JSON dla nowego dokumentu.
Step 3 - Ponieważ jest to wprowadzanie danych surowych, przejdźmy do naszego pierwszego dokumentu.
{
"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
}
Po wejściu do powyższego dokumentu zobaczysz następujący ekran.
Zauważ, że podaliśmy identyfikator dokumentu. Wartość id jest zawsze wymagana i musi być unikalna dla wszystkich innych dokumentów w tej samej kolekcji. Gdy go pominiesz, DocumentDB automatycznie wygeneruje go za pomocą identyfikatora GUID lub unikatowego identyfikatora globalnego.
Identyfikator jest zawsze łańcuchem i nie może być liczbą, datą, wartością logiczną ani innym obiektem i nie może być dłuższy niż 255 znaków.
Zwróć także uwagę na hierarchiczną strukturę dokumentu, która ma kilka właściwości najwyższego poziomu, takich jak wymagany id, a także lastName i isRegistered, ale ma również właściwości zagnieżdżone.
Na przykład właściwość parent jest dostarczana jako tablica JSON, oznaczona nawiasami kwadratowymi. Mamy również inną tablicę dla dzieci, mimo że w tym przykładzie jest tylko jedno dziecko w tablicy.
Step 4 - Kliknij przycisk „Zapisz”, aby zapisać dokument i stworzyliśmy nasz pierwszy dokument.
Jak widać, w naszym formacie JSON zastosowano ładne formatowanie, które rozbija każdą właściwość w osobnym wierszu z wcięciem spacją, aby przekazać poziom zagnieżdżenia każdej właściwości.
Portal zawiera eksplorator dokumentów, więc użyjmy go teraz, aby pobrać właśnie utworzony dokument.
Step 5- Wybierz bazę danych i dowolną kolekcję w bazie danych, aby wyświetlić dokumenty w tej kolekcji. Obecnie mamy tylko jedną bazę danych o nazwie myfirstdb z jedną kolekcją o nazwie Rodziny, z których obie zostały wstępnie wybrane na listach rozwijanych.
Domyślnie Eksplorator dokumentów wyświetla niefiltrowaną listę dokumentów w kolekcji, ale można także wyszukiwać dowolny określony dokument według identyfikatora lub wielu dokumentów na podstawie wyszukiwania wieloznacznego częściowego identyfikatora.
Jak dotąd mamy tylko jeden dokument w naszej kolekcji, a jego identyfikator widzimy na następnym ekranie, AndersonFamily.
Step 6 - Kliknij identyfikator, aby wyświetlić dokument.
Tworzenie dokumentów za pomocą zestawu .NET SDK
Jak wiesz, dokumenty to tylko inny rodzaj zasobów i już wiesz, jak traktować zasoby za pomocą zestawu SDK.
Jedna duża różnica między dokumentami a innymi zasobami polega na tym, że są one oczywiście wolne od schematów.
Tak więc istnieje wiele opcji. Oczywiście możesz po prostu pracować z grafami obiektów JSON, a nawet nieprzetworzonymi ciągami tekstu JSON, ale możesz także używać obiektów dynamicznych, które umożliwiają tworzenie powiązań z właściwościami w czasie wykonywania bez definiowania klasy w czasie kompilacji.
Możesz także pracować z rzeczywistymi obiektami C # lub encjami, jak są one nazywane, które mogą być klasami domeny biznesowej.
Zacznijmy tworzyć dokumenty przy użyciu .Net SDK. Oto kroki.
Step 1 - Utwórz instancję DocumentClient, a następnie zapytamy o bazę danych myfirstdb, a następnie o kolekcję MyCollection, którą przechowujemy w tej prywatnej kolekcji zmiennych, aby była dostępna w całej klasie.
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 - Utwórz dokumenty w zadaniu 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();
}
Pierwszy dokument zostanie wygenerowany z tego dynamicznego obiektu. To może wyglądać jak JSON, ale oczywiście tak nie jest. To jest kod C # i tworzymy rzeczywisty obiekt .NET, ale nie ma definicji klasy. Zamiast tego właściwości są wywnioskowane ze sposobu inicjowania obiektu.
Zauważ, że nie podaliśmy właściwości Id dla tego dokumentu.
Przyjrzyjmy się teraz CreateDocument. Wygląda jak ten sam wzorzec, który widzieliśmy przy tworzeniu baz danych i kolekcji.
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- Tym razem wywołujemy CreateDocumentAsync, określając SelfLink kolekcji, do której chcemy dodać dokument. Otrzymujemy odpowiedź z właściwością zasobu, która w tym przypadku reprezentuje nowy dokument z jego właściwościami wygenerowanymi przez system.
Obiekt Document jest zdefiniowaną klasą w SDK, która dziedziczy po zasobie, a więc ma wszystkie typowe właściwości zasobów, ale zawiera również właściwości dynamiczne, które definiują sam dokument bez schematu.
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();
}
Kiedy powyższy kod zostanie skompilowany i wykonany, otrzymasz następujące dane wyjściowe.
**** 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
Jak widać, nie dostarczyliśmy identyfikatora, jednak DocumentDB wygenerował go dla nas dla nowego dokumentu.
W usłudze DocumentDB faktycznie używamy SQL do tworzenia zapytań o dokumenty, więc ten rozdział dotyczy zapytań przy użyciu specjalnej składni SQL w DocumentDB. Chociaż jeśli tworzysz programowanie .NET, istnieje również dostawca LINQ, którego można użyć i który może generować odpowiedni kod SQL z zapytania LINQ.
Zapytanie o dokument za pomocą portalu
Portal Azure ma Eksplorator zapytań, który umożliwia uruchamianie dowolnego zapytania SQL w bazie danych DocumentDB.
Użyjemy Eksploratora zapytań, aby zademonstrować wiele różnych możliwości i funkcji języka zapytań, zaczynając od najprostszego możliwego zapytania.
Step 1 - W bloku bazy danych kliknij, aby otworzyć blok Eksplorator zapytań.
Pamiętaj, że zapytania są uruchamiane w zakresie kolekcji, dlatego Eksplorator zapytań umożliwia wybranie kolekcji z tego menu.
Step 2 - Wybierz kolekcję Rodziny, która została utworzona wcześniej przy użyciu portalu.
Eksplorator zapytań otwiera się za pomocą tego prostego zapytania SELECT * FROM c, które po prostu pobiera wszystkie dokumenty z kolekcji.
Step 3- Wykonaj zapytanie, klikając przycisk „Uruchom zapytanie”. Następnie zobaczysz, że cały dokument jest pobierany w bloku Wyniki.
Zapytanie o dokument przy użyciu .Net SDK
Poniżej przedstawiono kroki uruchamiania niektórych zapytań dotyczących dokumentów przy użyciu .Net SDK.
W tym przykładzie chcemy zapytać o nowo utworzone dokumenty, które właśnie dodaliśmy.
Step 1 - Wywołaj CreateDocumentQuery, przekazując kolekcję, w której zostanie uruchomione zapytanie za pomocą SelfLink i tekstu zapytania.
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();
}
To zapytanie zwraca również wszystkie dokumenty w całej kolekcji, ale nie wywołujemy .ToList w CreateDocumentQuery jak poprzednio, co spowodowałoby wysłanie tylu żądań, ile potrzeba, aby pobrać wszystkie wyniki w jednej linii kodu.
Step 2 - Zamiast tego wywołaj AsDocumentQuery, a ta metoda zwraca obiekt zapytania z właściwością HasMoreResults.
Step 3 - Jeśli HasMoreResults ma wartość true, wywołaj ExecuteNextAsync, aby pobrać następną porcję, a następnie zrzuć całą zawartość tej porcji.
Step 4- Jeśli wolisz, możesz również wykonywać zapytania przy użyciu LINQ zamiast SQL. Tutaj zdefiniowaliśmy zapytanie LINQ w q, ale nie zostanie ono wykonane, dopóki nie uruchomimy na nim .ToList.
private static void QueryDocumentsWithLinq(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("**** Query Documents (LINQ) ****");
Console.WriteLine();
Console.WriteLine("Quering for US customers (LINQ)");
var q =
from d in client.CreateDocumentQuery<Customer>(collection.DocumentsLink)
where d.Address.CountryRegionName == " United States"
select new {
Id = d.Id,
Name = d.Name,
City = d.Address.Location.City
};
var documents = q.ToList();
Console.WriteLine("Found {0} UK customers", documents.Count);
foreach (var document in documents) {
var d = document as dynamic;
Console.WriteLine(" Id: {0}; Name: {1}; City: {2}", d.Id, d.Name, d.City);
}
Console.WriteLine();
}
SDK przekształci nasze zapytanie LINQ w składnię SQL dla DocumentDB, generując klauzulę SELECT i WHERE na podstawie naszej składni LINQ
Step 5 - Teraz wywołaj powyższe zapytania z zadania 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);
}
}
Po wykonaniu powyższego kodu otrzymasz następujące dane wyjściowe.
**** 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
W tym rozdziale dowiemy się, jak aktualizować dokumenty. Korzystając z Azure Portal, możesz łatwo zaktualizować dokument, otwierając dokument w Eksploratorze dokumentów i aktualizując go w edytorze, takim jak plik tekstowy.
Kliknij przycisk „Zapisz”. Teraz, gdy musisz zmienić dokument za pomocą .Net SDK, możesz go po prostu zastąpić. Nie musisz go usuwać i odtwarzać, co oprócz tego, że jest żmudne, zmieniłoby również identyfikator zasobu, czego nie chciałbyś robić, gdy tylko modyfikujesz dokument. Oto następujące kroki, aby zaktualizować dokument za pomocą .Net SDK.
Rzućmy okiem na następujące zadanie ReplaceDocuments, w którym będziemy wyszukiwać dokumenty, w których właściwość isNew ma wartość true, ale nie otrzymamy żadnego, ponieważ żadnego nie ma. Zmodyfikujmy więc dokumenty, które dodaliśmy wcześniej, te, których nazwy zaczynają się od New Customer.
Step 1 - Dodaj właściwość isNew do tych dokumentów i ustaw jej wartość na 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 - Pobierz dokumenty do aktualizacji za pomocą tego samego zapytania STARTSWITH, a to daje nam dokumenty, które otrzymujemy jako obiekty dynamiczne.
Step 3 - Dołącz właściwość isNew i ustaw ją na true dla każdego dokumentu.
Step 4 - Wywołaj ReplaceDocumentAsync, przekazując SelfLink dokumentu wraz ze zaktualizowanym dokumentem.
Teraz, aby udowodnić, że to zadziałało, wyszukaj dokumenty, w których isNew jest równe prawdzie. Nazwijmy powyższe zapytania z zadania 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);
}
}
Gdy powyższy kod zostanie skompilowany i wykonany, otrzymasz następujące dane wyjściowe.
**** 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
W tym rozdziale dowiemy się, jak usunąć dokument z konta DocumentDB. Korzystając z Azure Portal, możesz łatwo usunąć dowolny dokument, otwierając dokument w Eksploratorze dokumentów i klikając opcję „Usuń”.
Wyświetli się komunikat potwierdzający. Teraz naciśnij przycisk Tak, a zobaczysz, że dokument nie jest już dostępny na Twoim koncie DocumentDB.
Teraz, gdy chcesz usunąć dokument za pomocą .Net SDK.
Step 1- Jest to ten sam wzorzec, który widzieliśmy wcześniej, w którym najpierw będziemy wykonywać zapytania, aby uzyskać SelfLinks każdego nowego dokumentu. Nie używamy tutaj SELECT *, który zwróciłby dokumenty w całości, których nie potrzebujemy.
Step 2 - Zamiast tego po prostu wybieramy SelfLink do listy, a następnie po prostu wywołujemy DeleteDocumentAsync dla każdego SelfLink, pojedynczo, aby usunąć dokumenty z kolekcji.
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 - Teraz wywołajmy powyższe DeleteDocuments z zadania 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);
}
}
Po wykonaniu powyższego kodu otrzymasz następujące dane wyjściowe.
***** Delete Documents *****
Quering for documents to be deleted
Found 2 documents to be deleted
Deleted 2 new customer documents
Chociaż bazy danych bez schematów, takie jak DocumentDB, bardzo ułatwiają wprowadzanie zmian w modelu danych, nadal powinieneś poświęcić trochę czasu na myślenie o swoich danych.
Masz wiele opcji. Oczywiście możesz po prostu pracować z grafami obiektów JSON, a nawet nieprzetworzonymi ciągami tekstu JSON, ale możesz także używać obiektów dynamicznych, które umożliwiają tworzenie powiązań z właściwościami w czasie wykonywania bez definiowania klasy w czasie kompilacji.
Możesz także pracować z rzeczywistymi obiektami C # lub encjami, jak są one nazywane, które mogą być klasami domeny biznesowej.
Relacje
Przyjrzyjmy się hierarchicznej strukturze dokumentu. Ma kilka właściwości najwyższego poziomu, takich jak wymagany id, a także lastName i isRegistered, ale ma również właściwości zagnieżdżone.
{
"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
}
Na przykład właściwość parent jest dostarczana jako tablica JSON, oznaczona nawiasami kwadratowymi.
Mamy również inną tablicę dla dzieci, mimo że w tym przykładzie jest tylko jedno dziecko w tablicy. W ten sposób modelujesz odpowiednik relacji jeden do wielu w dokumencie.
Po prostu używasz tablic, w których każdy element tablicy może być prostą wartością lub innym złożonym obiektem, a nawet inną tablicą.
Tak więc jedna rodzina może mieć wielu rodziców i wiele dzieci, a jeśli spojrzysz na obiekty podrzędne, mają one własność zwierzaka, która sama jest zagnieżdżoną tablicą dla relacji jeden do wielu między dziećmi a zwierzętami.
W przypadku właściwości lokalizacji łączymy w obiekt trzy powiązane właściwości - stan, hrabstwo i miasto.
Osadzanie obiektu w ten sposób zamiast osadzania tablicy obiektów jest podobne do relacji jeden do jednego między dwoma wierszami w oddzielnych tabelach w relacyjnej bazie danych.
Osadzanie danych
Rozpoczynając modelowanie danych w magazynie dokumentów, takim jak DocumentDB, spróbuj traktować encje jako samodzielne dokumenty reprezentowane w formacie JSON. Podczas pracy z relacyjnymi bazami danych zawsze normalizujemy dane.
Normalizacja danych zazwyczaj obejmuje przejęcie podmiotu, takiego jak klient, i podzielenie go na dyskretne fragmenty danych, takie jak dane kontaktowe i adresy.
Aby odczytać klienta, wraz ze wszystkimi jego danymi kontaktowymi i adresami, musisz użyć JOINS, aby skutecznie agregować dane w czasie wykonywania.
Przyjrzyjmy się teraz, jak modelowalibyśmy te same dane jako samodzielną jednostkę w bazie danych dokumentów.
{
"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}
]
}
Jak widać, zdenormalizowaliśmy rekord klienta, w którym wszystkie informacje o kliencie są osadzone w jednym dokumencie JSON.
W NoSQL mamy darmowy schemat, więc możesz dodawać dane kontaktowe i adresy również w innym formacie. W NoSQL można pobrać rekord klienta z bazy danych w jednej operacji odczytu. Podobnie aktualizowanie rekordu jest również pojedynczą operacją zapisu.
Poniżej przedstawiono kroki tworzenia dokumentów za pomocą .Net SDK.
Step 1- Utwórz wystąpienie DocumentClient. Następnie zapytamy o bazę danych myfirstdb, a także o kolekcję MyCollection, którą przechowujemy w tej prywatnej kolekcji zmiennych, aby była dostępna w całej klasie.
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 - Utwórz dokumenty w zadaniu 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();
}
Pierwszy dokument zostanie wygenerowany z tego dynamicznego obiektu. To może wyglądać jak JSON, ale oczywiście tak nie jest. To jest kod C # i tworzymy rzeczywisty obiekt .NET, ale nie ma definicji klasy. Zamiast tego właściwości są wywnioskowane ze sposobu inicjalizacji obiektu. Możesz również zauważyć, że nie dostarczyliśmy właściwości Id dla tego dokumentu.
Step 3 - Rzućmy teraz okiem na CreateDocument i wygląda jak ten sam wzorzec, który widzieliśmy przy tworzeniu baz danych i kolekcji.
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- Tym razem wywołujemy CreateDocumentAsync, określając SelfLink kolekcji, do której chcemy dodać dokument. Otrzymujemy odpowiedź z właściwością zasobu, która w tym przypadku reprezentuje nowy dokument z jego właściwościami wygenerowanymi przez system.
W kolejnym zadaniu CreateDocuments utworzyliśmy trzy dokumenty.
W pierwszym dokumencie obiekt Document jest zdefiniowaną klasą w SDK, która dziedziczy po zasobie, a więc ma wszystkie typowe właściwości zasobu, ale zawiera również właściwości dynamiczne, które definiują sam dokument bez schematu.
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();
}
Ten drugi dokument działa tylko z nieprzetworzonym ciągiem JSON. Teraz przechodzimy do przeciążenia dla CreateDocument, które używa JavaScriptSerializer do deserializacji ciągu do obiektu, który następnie przekazuje do tej samej metody CreateDocument, której użyliśmy do utworzenia pierwszego dokumentu.
W trzecim dokumencie wykorzystaliśmy obiekt C # Customer zdefiniowany w naszej aplikacji.
Przyjrzyjmy się temu klientowi, ma on właściwość Id i address, w której adres jest obiektem zagnieżdżonym z własnymi właściwościami, w tym lokalizacją, który jest kolejnym obiektem zagnieżdżonym.
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; }
}
}
Mamy też atrybuty właściwości JSON, ponieważ chcemy zachować odpowiednie konwencje po obu stronach ogrodzenia.
Dlatego po prostu tworzę obiekt New Customer wraz z jego zagnieżdżonymi obiektami podrzędnymi i jeszcze raz wywołuję CreateDocument. Chociaż nasz obiekt klienta ma właściwość Id, nie podaliśmy dla niego wartości, więc DocumentDB wygenerował ją na podstawie identyfikatora GUID, tak jak w przypadku poprzednich dwóch dokumentów.
Kiedy powyższy kod zostanie skompilowany i wykonany, otrzymasz następujące dane wyjściowe.
**** 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 lub JavaScript Object Notation to lekki, oparty na tekście, otwarty standard przeznaczony do wymiany danych czytelnych dla człowieka, a także łatwy do analizowania i generowania przez maszyny. JSON jest sercem DocumentDB. Przesyłamy JSON przez sieć, przechowujemy JSON jako JSON i indeksujemy drzewo JSON, umożliwiając zapytania dotyczące pełnego dokumentu JSON.
Format JSON obsługuje następujące typy danych -
S.No. | Typ i opis |
---|---|
1 | Number Format zmiennoprzecinkowy podwójnej precyzji w JavaScript |
2 | String Unicode w podwójnym cudzysłowie z ukośnikiem odwrotnym |
3 | Boolean Prawda czy fałsz |
4 | Array Uporządkowana sekwencja wartości |
5 | Value Może to być ciąg, liczba, prawda lub fałsz, null itp. |
6 | Object Nieuporządkowana kolekcja par klucz: wartość |
7 | Whitespace Można go używać między dowolnymi parami tokenów |
8 | Null Pusty |
Rzućmy okiem na prosty przykład typu DateTime. Dodaj datę urodzenia do klasy klienta.
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; }
}
Możemy przechowywać, pobierać i wykonywać zapytania przy użyciu DateTime, jak pokazano w poniższym kodzie.
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();
}
Kiedy powyższy kod zostanie skompilowany i wykonany, a dokument zostanie utworzony, zobaczysz, że data urodzenia została dodana.
**** 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
Firma Microsoft niedawno dodała szereg ulepszeń dotyczących sposobu wykonywania zapytań Azure DocumentDB, takich jak słowo kluczowe TOP do gramatyki SQL, dzięki czemu zapytania działają szybciej i zużywają mniej zasobów, zwiększono limity dla operatorów zapytań i dodano obsługę dodatkowych operatorów LINQ w zestaw .NET SDK.
Spójrzmy na prosty przykład, w którym pobierzemy tylko pierwsze dwa rekordy. Jeśli masz kilka rekordów i chcesz pobrać tylko niektóre z nich, możesz użyć słowa kluczowego Top. W tym przykładzie mamy wiele zapisów dotyczących trzęsień ziemi.
Teraz chcemy pokazać tylko pierwsze dwa rekordy
Step 1 - Przejdź do eksploratora zapytań i uruchom to zapytanie.
SELECT * FROM c
WHERE c.magnitude > 2.5
Zobaczysz, że pobrał cztery rekordy, ponieważ nie określiliśmy jeszcze słowa kluczowego TOP.
Step 2- Teraz użyj słowa kluczowego TOP z tym samym zapytaniem. Tutaj określiliśmy słowo kluczowe TOP, a „2” oznacza, że chcemy tylko dwóch rekordów.
SELECT TOP 2 * FROM c
WHERE c.magnitude > 2.5
Step 3 - Teraz uruchom to zapytanie, a zobaczysz, że zostały pobrane tylko dwa rekordy.
Podobnie możesz użyć słowa kluczowego TOP w kodzie za pomocą .Net SDK. Poniżej znajduje się realizacja.
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();
}
Poniżej przedstawiono zadanie CreateDocumentClient, w którym tworzone są wystąpienia bazy danych DocumentClient i trzęsienia ziemi.
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);
}
}
Kiedy powyższy kod zostanie skompilowany i wykonany, zobaczysz, że pobierane są tylko trzy rekordy.
**** Query Documents (paged results) ****
Quering for all documents
PublicId: 2015p947400; Magnitude: 2.515176918;
PublicId: 2015p947373; Magnitude: 1.506774108;
PublicId: 2015p947329; Magnitude: 1.593394461;
Microsoft Azure DocumentDB obsługuje tworzenie zapytań dotyczących dokumentów przy użyciu języka SQL zamiast dokumentów JSON. Możesz sortować dokumenty w kolekcji według liczb i ciągów znaków za pomocą klauzuli ORDER BY w zapytaniu. Klauzula może zawierać opcjonalny argument ASC / DESC w celu określenia kolejności, w jakiej należy pobierać wyniki.
Spójrzmy na poniższy przykład, w którym mamy dokument 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
}
]
}
Poniżej znajduje się zapytanie SQL służące do sortowania wyniku w porządku malejącym.
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
Po wykonaniu powyższego zapytania otrzymasz następujące dane wyjściowe.
[
{
"description": "Grapes, red or green (European type, such as Thompson
seedless), raw",
"foodGroup": "Fruits and Fruit Juices",
"servingDescription": "NLEA serving",
"servingWeight": 126
}
]
Domyślnie DocumentDB automatycznie indeksuje każdą właściwość w dokumencie, gdy tylko dokument zostanie dodany do bazy danych. Możesz jednak przejąć kontrolę i dostroić własne zasady indeksowania, które zmniejszają obciążenie związane z przechowywaniem i przetwarzaniem, gdy istnieją określone dokumenty i / lub właściwości, które nigdy nie wymagają indeksowania.
Domyślna zasada indeksowania, która nakazuje usłudze DocumentDB indeksowanie każdej właściwości automatycznie, jest odpowiednia dla wielu typowych scenariuszy. Ale możesz również wdrożyć niestandardowe zasady, które dokładnie kontrolują to, co jest indeksowane, a co nie, oraz inne funkcje związane z indeksowaniem.
DocumentDB obsługuje następujące typy indeksowania -
- Hash
- Range
Haszysz
Hash index umożliwia wydajne sprawdzanie równości, tj. Podczas wyszukiwania dokumentów, w których dana właściwość jest równa dokładnej wartości, zamiast dopasowywania do zakresu wartości, takich jak mniej niż, większe niż lub pomiędzy.
Możesz wykonywać zapytania o zakres z indeksem skrótu, ale DocumentDB nie będzie w stanie użyć indeksu skrótu do znalezienia pasujących dokumentów i zamiast tego będzie musiał sekwencyjnie skanować każdy dokument, aby określić, czy powinien zostać wybrany przez zapytanie o zakres.
Nie będziesz w stanie sortować dokumentów za pomocą klauzuli ORDER BY we właściwości, która ma tylko indeks skrótu.
Zasięg
Indeks zakresu zdefiniowany dla właściwości, DocumentDB umożliwia wydajne wyszukiwanie dokumentów w oparciu o zakres wartości. Pozwala również na sortowanie wyników zapytań dotyczących tej właściwości za pomocą ORDER BY.
DocumentDB umożliwia zdefiniowanie zarówno skrótu, jak i indeksu zakresu dla dowolnej lub wszystkich właściwości, co umożliwia wydajne zapytania o równość i zakres, a także ORDER BY.
Zasady indeksowania
Każda kolekcja ma zasady indeksowania, które dyktują, jakie typy indeksów są używane dla liczb i ciągów znaków w każdej właściwości każdego dokumentu.
Możesz także kontrolować, czy dokumenty mają być indeksowane automatycznie, gdy są dodawane do kolekcji.
Automatyczne indeksowanie jest domyślnie włączone, ale można zmienić to zachowanie podczas dodawania dokumentu, informując DocumentDB, aby nie indeksował tego konkretnego dokumentu.
Można wyłączyć automatyczne indeksowanie, aby domyślnie dokumenty nie były indeksowane po dodaniu do kolekcji. Podobnie możesz to zmienić na poziomie dokumentu i poinstruować DocumentDB, aby indeksował określony dokument podczas dodawania go do kolekcji. Nazywa się to ręcznym indeksowaniem.
Uwzględnij / wyklucz indeksowanie
Zasady indeksowania mogą również określać, która ścieżka lub ścieżki powinny być uwzględnione lub wykluczone z indeksu. Jest to przydatne, jeśli wiesz, że istnieją pewne części dokumentu, w odniesieniu do których nigdy nie wykonujesz zapytań, i pewne części, które robisz.
W takich przypadkach można zmniejszyć obciążenie związane z indeksowaniem, nakazując usłudze DocumentDB indeksowanie tylko tych określonych części każdego dokumentu dodanego do kolekcji.
Automatyczne indeksowanie
Spójrzmy na prosty przykład automatycznego indeksowania.
Step 1 - Najpierw tworzymy kolekcję o nazwie autoindexing i bez jawnego dostarczania zasad, ta kolekcja korzysta z domyślnych zasad indeksowania, co oznacza, że automatyczne indeksowanie jest włączone w tej kolekcji.
W tym przypadku używamy routingu opartego na identyfikatorach dla samodzielnego łączenia bazy danych, więc nie musimy znać jego identyfikatora zasobu ani zapytać o niego przed utworzeniem kolekcji. Możemy po prostu użyć identyfikatora bazy danych, którym jest mydb.
Step 2 - Teraz utwórzmy dwa dokumenty, oba z nazwiskiem 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");
}
Ten pierwszy, dla Mark Upston, jest dodawany do kolekcji, a następnie jest natychmiast indeksowany automatycznie na podstawie domyślnych zasad indeksowania.
Ale po dodaniu drugiego dokumentu dla Mark Upston przekazaliśmy opcje żądania za pomocą IndexingDirective.Exclude, która wyraźnie instruuje DocumentDB, aby nie indeksować tego dokumentu, pomimo zasad indeksowania kolekcji.
Na końcu mamy różne rodzaje zapytań do obu dokumentów.
Step 3 - Wywołajmy zadanie AutomaticIndexing z 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);
}
}
Gdy powyższy kod zostanie skompilowany i wykonany, otrzymasz następujące dane wyjściowe.
**** Override Automatic Indexing ****
Documents WHERE lastName = 'Upston': 1
All documents: 2
Unindexed document self-link: dbs/kV5oAA==/colls/kV5oAOEkfQA=/docs/kV5oAOEkfQACA
AAAAAAAAA==/
Jak widać, mamy dwa takie dokumenty, ale zapytanie zwraca tylko ten dotyczący Marka, ponieważ ten dotyczący Marka nie jest indeksowany. Jeśli ponownie zapytamy, bez klauzuli WHERE w celu pobrania wszystkich dokumentów w kolekcji, otrzymamy zestaw wyników z obydwoma dokumentami, a dzieje się tak, ponieważ niezindeksowane dokumenty są zawsze zwracane przez zapytania, które nie mają klauzuli WHERE.
Możemy również odzyskać niezindeksowane dokumenty za pomocą ich identyfikatora lub linku własnego. Kiedy więc wyszukujemy dokument Marka za pomocą jego identyfikatora MARK, widzimy, że DocumentDB zwraca dokument, mimo że nie jest indeksowany w kolekcji.
Indeksowanie ręczne
Przyjrzyjmy się prostemu przykładowi ręcznego indeksowania przez zastąpienie automatycznego indeksowania.
Step 1- Najpierw utworzymy kolekcję o nazwie manualindexing i zastąpimy domyślne zasady, jawnie wyłączając automatyczne indeksowanie. Oznacza to, że o ile nie zażądamy inaczej, nowe dokumenty dodawane do tej kolekcji nie będą indeksowane.
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- Teraz ponownie utworzymy te same dwa dokumenty, co poprzednio. Tym razem nie dostarczymy żadnych specjalnych opcji żądania dla dokumentu Marka, ponieważ z powodu zasad indeksowania kolekcji ten dokument nie zostanie zindeksowany.
Step 3 - Teraz, kiedy dodajemy drugi dokument dla Mark, używamy RequestOptions z IndexingDirective.Include, aby poinformować DocumentDB, że powinien indeksować ten dokument, co zastępuje politykę indeksowania kolekcji, która mówi, że nie powinna.
Na końcu mamy różne rodzaje zapytań do obu dokumentów.
Step 4 - Nazwijmy zadanie ManualIndexing z 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);
}
}
Kiedy powyższy kod zostanie skompilowany i wykonany, otrzymasz następujące dane wyjściowe.
**** Manual Indexing ****
Documents WHERE lastName = 'Upston': 1
All documents: 2
Unindexed document self-link: dbs/kV5oAA==/colls/kV5oANHJPgE=/docs/kV5oANHJPgEBA
AAAAAAAAA==/
Ponownie zapytanie zwraca tylko jeden z dwóch dokumentów, ale tym razem zwraca Jane Doe, o której indeksowanie wyraźnie zażądaliśmy. Ale znowu, jak poprzednio, zapytanie bez klauzuli WHERE powoduje pobranie wszystkich dokumentów w kolekcji, w tym niezindeksowanego dokumentu dla Marka. Możemy również zapytać o niezindeksowany dokument według jego identyfikatora, który DocumentDB zwraca, mimo że nie jest indeksowany.
Microsoft dodał geospatial support, który umożliwia przechowywanie danych lokalizacji w dokumentach i wykonywanie obliczeń przestrzennych dla odległości i przecięć między punktami i wielokątami.
Dane przestrzenne opisują położenie i kształt obiektów w przestrzeni.
Zwykle może służyć do reprezentowania lokalizacji osoby, interesującego miejsca lub granicy miasta lub jeziora.
Typowe przypadki użycia często obejmują zapytania zbliżeniowe. Na przykład „znajdź wszystkie uniwersytety w pobliżu mojej bieżącej lokalizacji”.
ZA Pointoznacza pojedynczą pozycję w przestrzeni, która reprezentuje dokładną lokalizację, np. adres danej uczelni. Punkt jest reprezentowany w DocumentDB za pomocą jego pary współrzędnych (długość i szerokość geograficzna). Poniżej znajduje się przykład punktu JSON.
{
"type":"Point",
"coordinates":[ 28.3, -10.7 ]
}
Przyjrzyjmy się prostemu przykładowi zawierającemu lokalizację uczelni.
{
"id":"case-university",
"name":"CASE: Center For Advanced Studies In Engineering",
"city":"Islamabad",
"location": {
"type":"Point",
"coordinates":[ 33.7194136, -73.0964862 ]
}
}
Aby pobrać nazwę uczelni na podstawie lokalizacji, możesz użyć następującego zapytania.
SELECT c.name FROM c
WHERE c.id = "case-university" AND ST_ISVALID({
"type":"Point",
"coordinates":[ 33.7194136, -73.0964862 ]})
Po wykonaniu powyższego zapytania otrzymasz następujące dane wyjściowe.
[
{
"name": "CASE: Center For Advanced Studies In Engineering"
}
]
Utwórz dokument z danymi geoprzestrzennymi w .NET
Możesz stworzyć dokument z danymi geoprzestrzennymi, spójrzmy na prosty przykład, w którym tworzony jest dokument uniwersytecki.
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();
}
Poniżej znajduje się implementacja dla klasy 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; }
}
Gdy powyższy kod zostanie skompilowany i wykonany, otrzymasz następujące dane wyjściowe.
**** 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
Gdy baza danych zacznie się rozrastać powyżej 10 GB, możesz ją skalować, po prostu tworząc nowe kolekcje, a następnie rozmieszczając lub dzieląc dane na coraz więcej kolekcji.
Wcześniej czy później pojedynczy zbiór, który ma pojemność 10 GB, nie wystarczy do przechowywania bazy danych. Teraz 10 GB może nie brzmieć jak bardzo duża liczba, ale pamiętaj, że przechowujemy dokumenty JSON, które są zwykłym tekstem i możesz zmieścić wiele zwykłych dokumentów tekstowych w 10 GB, nawet jeśli weźmiesz pod uwagę narzut pamięci na indeksy.
Pamięć masowa to nie jedyny problem, jeśli chodzi o skalowalność. Maksymalna przepustowość dostępna w kolekcji to dwa i pół tysiąca jednostek żądań na sekundę, które uzyskuje się dzięki kolekcji S3. Dlatego jeśli potrzebujesz większej przepustowości, będziesz musiał również skalować w poziomie przez partycjonowanie wielu kolekcji. Nazywa się również partycjonowanie skalowane w poziomiehorizontal partitioning.
Istnieje wiele podejść, których można użyć do partycjonowania danych za pomocą Azure DocumentDB. Oto najczęstsze strategie -
- Partycjonowanie spillover
- Podział zakresu
- Partycjonowanie wyszukiwania
- Hash Partitioning
Partycjonowanie spillover
Partycjonowanie typu spillover jest najprostszą strategią, ponieważ nie ma klucza partycji. Często jest to dobry wybór, gdy nie masz pewności co do wielu rzeczy. Możesz nie wiedzieć, czy kiedykolwiek będziesz musiał przeskalować poza pojedynczą kolekcję lub ile kolekcji będziesz musiał dodać lub jak szybko będziesz musiał je dodać.
Partycjonowanie typu spillover rozpoczyna się od pojedynczej kolekcji i nie ma klucza partycji.
Kolekcja zaczyna się rozrastać, a potem powiększa się trochę bardziej, potem trochę bardziej, aż zbliżasz się do limitu 10 GB.
Gdy osiągniesz 90 procent pojemności, przejdziesz do nowej kolekcji i zaczniesz używać jej do nowych dokumentów.
Gdy baza danych zostanie przeskalowana do większej liczby kolekcji, prawdopodobnie będziesz chciał przejść do strategii opartej na kluczu partycji.
Kiedy to zrobisz, będziesz musiał zrównoważyć swoje dane, przenosząc dokumenty do różnych kolekcji w oparciu o dowolną strategię, do której migrujesz.
Podział zakresu
Jedną z najpopularniejszych strategii jest podział zakresu. W tym podejściu określasz zakres wartości, do których może należeć klucz partycji dokumentu, i kierujesz dokument do kolekcji odpowiadającej temu zakresowi.
Daty są bardzo często używane w tej strategii, gdy tworzysz kolekcję do przechowywania dokumentów mieszczących się w zdefiniowanym zakresie dat. Gdy zdefiniujesz wystarczająco małe zakresy, masz pewność, że żadna kolekcja nigdy nie przekroczy swojego limitu 10 GB. Na przykład może istnieć scenariusz, w którym pojedyncza kolekcja może rozsądnie obsługiwać dokumenty przez cały miesiąc.
Może się również zdarzyć, że większość użytkowników pyta o aktualne dane, które byłyby danymi z tego miesiąca lub być może z ostatniego miesiąca, ale użytkownicy rzadko wyszukują znacznie starsze dane. Zaczynasz więc w czerwcu od kolekcji S3, która jest najdroższą kolekcją, jaką możesz kupić i zapewnia najlepszą wydajność, jaką możesz uzyskać.
W lipcu kupujesz kolejną kolekcję S3 do przechowywania danych z lipca, a także skalujesz dane czerwcowe do tańszej kolekcji S2. Następnie w sierpniu otrzymujesz kolejną kolekcję S3 i przeskalujesz lipiec do S2, a czerwiec aż do S1. Odbywa się to miesiąc po miesiącu, gdzie zawsze masz dostęp do aktualnych danych dla wysokiej przepustowości, a starsze dane są dostępne przy niższej przepustowości.
Tak długo, jak zapytanie dostarcza klucz partycji, tylko kolekcja, która ma zostać odpytana, zostanie zapytana, a nie wszystkie kolekcje w bazie danych, tak jak ma to miejsce w przypadku partycjonowania spillover.
Partycjonowanie wyszukiwania
Dzięki partycjonowaniu wyszukiwania można zdefiniować mapę partycji, która kieruje dokumenty do określonych kolekcji na podstawie ich klucza partycji. Na przykład możesz podzielić według regionu.
Przechowuj wszystkie dokumenty ze Stanów Zjednoczonych w jednej kolekcji, wszystkie dokumenty europejskie w innej kolekcji, a wszystkie dokumenty z dowolnego regionu w trzeciej kolekcji.
Skorzystaj z tej mapy partycji i narzędzia do rozpoznawania partycji wyszukiwania, aby dowiedzieć się, w której kolekcji należy utworzyć dokument i do których kolekcji należy przeszukiwać, na podstawie klucza partycji, który jest właściwością regionu zawartą w każdym dokumencie.
Hash Partitioning
W przypadku partycjonowania skrótu partycje są przypisywane na podstawie wartości funkcji skrótu, co umożliwia równomierne rozłożenie żądań i danych na wiele partycji.
Jest to powszechnie używane do partycjonowania danych generowanych lub wykorzystywanych przez dużą liczbę różnych klientów i jest przydatne do przechowywania profili użytkowników, pozycji katalogu itp.
Rzućmy okiem na prosty przykład partycjonowania zakresu przy użyciu RangePartitionResolver dostarczonego przez .NET SDK.
Step 1- Utwórz nowy DocumentClient, a my utworzymy dwie kolekcje w zadaniu CreateCollections. Jeden będzie zawierał dokumenty dla użytkowników, których identyfikatory użytkowników rozpoczynają się od A do M, a drugi dla identyfikatorów użytkowników od N do 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 - Zarejestruj program rozpoznawania zakresu dla bazy danych.
Step 3- Utwórz nowy RangePartitionResolver <string>, który jest typem danych naszego klucza partycji. Konstruktor przyjmuje dwa parametry, nazwę właściwości klucza partycji i słownik, który jest mapą fragmentów lub mapą partycji, która jest po prostu listą zakresów i odpowiadających im kolekcji, które wstępnie definiujemy dla programu rozpoznawania nazw.
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;
}
Konieczne jest tutaj zakodowanie największej możliwej wartości UTF-8. Albo pierwszy zakres nie pasowałby do żadnego M poza jednym M, podobnie jak Z w drugim zakresie. Możesz więc po prostu pomyśleć o tej zakodowanej wartości tutaj jako o symbolu wieloznacznym do dopasowania klucza partycji.
Step 4- Po utworzeniu resolwera zarejestruj go w bazie danych przy użyciu bieżącego DocumentClient. Aby to zrobić, wystarczy przypisać go do właściwości słownika PartitionResolver.
Będziemy tworzyć i wyszukiwać dokumenty w bazie danych, a nie w kolekcji, jak zwykle. Program rozpoznawania nazw użyje tej mapy do kierowania żądań do odpowiednich kolekcji.
Teraz stwórzmy kilka dokumentów. Najpierw utworzymy jeden dla userId Kirk, a potem drugi dla Spocka.
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);
}
Pierwszym parametrem jest tutaj łącze do bazy danych, a nie konkretna kolekcja. Nie jest to możliwe bez programu do rozpoznawania partycji, ale z jednym działa po prostu bezproblemowo.
Oba dokumenty zostały zapisane w bazie danych myfirstdb, ale wiemy, że Kirk jest przechowywany w kolekcji od A do M, a Spock jest przechowywany w kolekcji od N do Z, jeśli nasz RangePartitionResolver działa poprawnie.
Wywołajmy je z zadania CreateDocumentClient, jak pokazano w poniższym kodzie.
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);
}
}
Po wykonaniu powyższego kodu otrzymasz następujące dane wyjściowe.
**** Create Documents Across Partitions ****
Document 1: dbs/Ic8LAA==/colls/Ic8LAO2DxAA=/docs/Ic8LAO2DxAABAAAAAAAAAA==/
Document 2: dbs/Ic8LAA==/colls/Ic8LAP12QAE=/docs/Ic8LAP12QAEBAAAAAAAAAA==/
Jak widać, łącza własne tych dwóch dokumentów mają różne identyfikatory zasobów, ponieważ istnieją w dwóch oddzielnych kolekcjach.
Dzięki narzędziu do migracji danych z bazy danych DocumentDB możesz łatwo migrować dane do bazy danych DocumentDB. Narzędzie do migracji danych usługi DocumentDB to bezpłatne narzędzie typu open source, które można pobrać z Centrum pobierania Microsofthttps://www.microsoft.com/
Narzędzie do migracji obsługuje wiele źródeł danych, niektóre z nich są wymienione poniżej -
- SQL Server
- Pliki JSON
- Pliki płaskie z wartościami oddzielonymi przecinkami (CSV)
- MongoDB
- Magazyn tabel Azure
- Amazon DynamoDB
- HBase, a nawet inne bazy danych DocumentDB
Po pobraniu narzędzia do migracji danych usługi DocumentDB wyodrębnij plik zip.
Możesz zobaczyć dwa pliki wykonywalne w tym folderze, jak pokazano na poniższym zrzucie ekranu.
Najpierw jest dt.exe, który jest wersją konsolową z interfejsem wiersza poleceń, a następnie jest dtui.exe, który jest wersją desktopową z graficznym interfejsem użytkownika.
Uruchommy wersję GUI.
Możesz zobaczyć stronę powitalną. Kliknij „Dalej” na stronie Informacje o źródle.
Tutaj możesz skonfigurować źródło danych i zobaczyć wiele obsługiwanych opcji z menu rozwijanego.
Po dokonaniu wyboru reszta strony Informacje o źródle odpowiednio się zmienia.
Importowanie danych do DocumentDB jest bardzo łatwe przy użyciu narzędzia do migracji danych DocumentDB. Zalecamy przećwiczenie powyższych przykładów i użycie innych plików danych.
DocumentDB zapewnia koncepcje kontrolowania dostępu do zasobów DocumentDB. Dostęp do zasobów DocumentDB jest zarządzany przez token klucza głównego lub token zasobów. Połączenia oparte na tokenach zasobów mogą uzyskiwać dostęp tylko do zasobów określonych przez tokeny, a nie do innych zasobów. Tokeny zasobów są oparte na uprawnieniach użytkowników.
Najpierw tworzysz jednego lub więcej użytkowników i są oni definiowani na poziomie bazy danych.
Następnie utwórz jedno lub więcej uprawnień dla każdego użytkownika na podstawie zasobów, do których chcesz zezwolić każdemu użytkownikowi.
Każde uprawnienie generuje token zasobu, który umożliwia dostęp tylko do odczytu lub pełny dostęp do danego zasobu i może to być dowolny zasób użytkownika w bazie danych.
Użytkownicy są definiowani na poziomie bazy danych, a uprawnienia są definiowane dla każdego użytkownika.
Użytkownicy i uprawnienia mają zastosowanie do wszystkich kolekcji w bazie danych.
Przyjrzyjmy się prostemu przykładowi, w którym nauczymy się definiować użytkowników i uprawnienia, aby uzyskać szczegółowe bezpieczeństwo w DocumentDB.
Zaczniemy od nowego DocumentClient i wyszukamy bazę danych 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");
}
}
Poniżej znajduje się implementacja narzędzia 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- Utwórz dwóch użytkowników, Alicję i Tomka, jak każdy inny zasób, który tworzymy, konstruujemy obiekt definicji z żądanym identyfikatorem i wywołujemy metodę tworzenia, aw tym przypadku wywołujemy CreateUserAsync za pomocą SelfLink bazy danych i userDefinition. Otrzymujemy wynik, z którego właściwości zasobu otrzymujemy nowo utworzony obiekt użytkownika.
Teraz, aby zobaczyć tych dwóch nowych użytkowników w bazie danych.
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- Wywołaj CreateUserQuery, korzystając z UsersLink bazy danych, aby pobrać listę wszystkich użytkowników. Następnie przejrzyj je i zobacz ich właściwości.
Teraz musimy je najpierw stworzyć. Powiedzmy więc, że chcieliśmy przyznać Alicji uprawnienia do odczytu / zapisu kolekcji MyCollection, ale Tomek może czytać tylko dokumenty w tej kolekcji.
await CreatePermission(client, alice, "Alice Collection Access", PermissionMode.All,
collection);
await CreatePermission(client, tom, "Tom Collection Access", PermissionMode.Read,
collection);
Step 3- Utwórz uprawnienie do zasobu, który jest kolekcją MyCollection, abyśmy mogli uzyskać dla tego zasobu SelfLink.
Step 4 - Następnie utwórz pozwolenie, wszystko w tej kolekcji dla Alicji i pozwolenie, przeczytaj tę kolekcję dla Toma.
Poniżej znajduje się implementacja metody 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);
}
Jak już można się było spodziewać, robimy to, tworząc obiekt definicji dla nowego uprawnienia, który zawiera identyfikator i tryb PermissionsMode, którym jest Permission.All lub Permission.Read oraz SelfLink zabezpieczanego zasobu za zgodą.
Step 5 - Wywołaj CreatePermissionAsync i uzyskaj utworzone uprawnienie z właściwości zasobu w wyniku.
Aby wyświetlić utworzone uprawnienia, poniżej przedstawiono implementację 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);
}
Tym razem jest to zapytanie o pozwolenie w odniesieniu do linku do uprawnień użytkownika, a po prostu podajemy listę wszystkich uprawnień zwróconych użytkownikowi.
Usuńmy uprawnienia Alicji i Toma.
await DeletePermission(client, alice, "Alice Collection Access");
await DeletePermission(client, tom, "Tom Collection Access");
Poniżej przedstawiono implementację metody 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 - Aby usunąć uprawnienia, zapytaj o identyfikator uprawnienia, aby uzyskać SelfLink, a następnie użyj SelfLink do usunięcia uprawnienia.
Następnie usuńmy samych użytkowników. Usuńmy obu użytkowników.
await DeleteUser(client, "Alice");
await DeleteUser(client, "Tom");
Poniżej znajduje się implementacja dla 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 - Najpierw zapytaj o jej SelfLink, a następnie wywołaj DeleteUserAsync, aby usunąć jej obiekt użytkownika.
Poniżej znajduje się realizacja zadania CreateDocumentClient, w którym wszystkie powyższe zadania nazywamy.
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");
}
}
Kiedy powyższy kod zostanie skompilowany i wykonany, otrzymasz następujące dane wyjściowe.
**** 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
W tym rozdziale dowiemy się, jak wizualizować dane przechowywane w DocumentDB. Dostarczone przez firmę Microsoft narzędzie Power BI Desktop, które przekształca dane w bogate wizualizacje. Umożliwia także pobieranie danych z różnych źródeł danych, scalanie i przekształcanie danych, tworzenie zaawansowanych raportów i wizualizacji oraz publikowanie raportów w usłudze Power BI.
W najnowszej wersji programu Power BI Desktop firma Microsoft dodała również obsługę usługi DocumentDB, w której możesz teraz łączyć się ze swoim kontem DocumentDB. Możesz pobrać to narzędzie z linku,https://powerbi.microsoft.com
Spójrzmy na przykład, w którym zwizualizujemy dane dotyczące trzęsień ziemi zaimportowane w poprzednim rozdziale.
Step 1 - Po pobraniu narzędzia uruchom pulpit Power BI.
Step 2 - Kliknij opcję „Pobierz dane”, która znajduje się na karcie Strona główna w grupie Dane zewnętrzne, a wyświetli się strona Pobierz dane.
Step 3 - Wybierz opcję Microsoft Azure DocumentDB (Beta) i kliknij przycisk „Połącz”.
Step 4 - Wprowadź adres URL swojego konta Azure DocumentDB, bazy danych i kolekcji, z których chcesz wizualizować dane, i naciśnij OK.
Jeśli łączysz się z tym punktem końcowym po raz pierwszy, zostanie wyświetlony monit o podanie klucza konta.
Step 5 - Wprowadź klucz konta (klucz podstawowy), który jest unikatowy dla każdego konta usługi DocumentDB dostępnego w witrynie Azure Portal, a następnie kliknij przycisk Połącz.
Gdy konto zostanie pomyślnie połączone, pobierze dane z określonej bazy danych. W okienku podglądu jest wyświetlana lista elementów rekordu, dokument jest reprezentowany jako typ rekordu w usłudze Power BI.
Step 6 - Kliknij przycisk „Edytuj”, co spowoduje uruchomienie Edytora zapytań.
Step 7 - W Edytorze zapytań usługi Power BI w środkowym okienku powinna być widoczna kolumna Dokument, kliknij ekspander po prawej stronie nagłówka kolumny Dokument i wybierz kolumny, które chcesz wyświetlić.
Jak widać, mamy szerokość i długość geograficzną jako oddzielną kolumnę, ale wizualizujemy dane w postaci współrzędnych szerokości i długości geograficznej.
Step 8 - Aby to zrobić, kliknij kartę „Dodaj kolumnę”.
Step 9 - Wybierz opcję Dodaj kolumnę niestandardową, która wyświetli następną stronę.
Step 10- Podaj nową nazwę kolumny, powiedzmy LatLong, a także formułę, która połączy szerokość i długość geograficzną w jednej kolumnie oddzielone przecinkiem. Oto wzór.
Text.From([latitude])&", "&Text.From([longitude])
Step 11 - Kliknij OK, aby kontynuować, a zobaczysz, że nowa kolumna została dodana.
Step 12 - Przejdź do zakładki Strona główna i kliknij opcję „Zamknij i zastosuj”.
Step 13- Możesz tworzyć raporty, przeciągając i upuszczając pola w kanwie raportów. Po prawej stronie widać dwa panele - jeden panel Wizualizacje, a drugi panel Pola.
Utwórzmy widok mapy pokazujący lokalizację każdego trzęsienia ziemi.
Step 14 - Przeciągnij typ wizualny mapy z okienka Wizualizacje.
Step 15- Teraz przeciągnij i upuść pole LatLong z panelu Pola do właściwości Lokalizacja w okienku Wizualizacje. Następnie przeciągnij i upuść pole wielkości do właściwości Values.
Step 16 - Przeciągnij i upuść pole głębi do właściwości Nasycenie koloru.
Zobaczysz teraz wizualizację mapy przedstawiającą zestaw bąbelków wskazujących lokalizację każdego trzęsienia ziemi.