DocumentDB-クイックガイド
この章では、NoSQLとドキュメントデータベースに関する主要な概念について簡単に説明します。DocumentDBの概要についても簡単に説明します。
NoSQLドキュメントデータベース
DocumentDBはMicrosoftの最新のNoSQLドキュメントデータベースです。NoSQLドキュメントデータベースと言えば、NoSQLとドキュメントデータベースとは正確にはどういう意味ですか?
SQLは、リレーショナルデータベースの従来のクエリ言語である構造化クエリ言語を意味します。SQLは、多くの場合、リレーショナルデータベースと同等です。
NoSQLデータベースを非リレーショナルデータベースと考えると非常に便利です。したがって、NoSQLは実際には非リレーショナルを意味します。
次のようなキー値ストアを含むさまざまなタイプのNoSQLデータベースがあります。
- Azureテーブルストレージ。
- Cassandraのような列ベースのストア。
- NEO4のようなグラフデータベース。
- MongoDBやAzureDocumentDBなどのドキュメントデータベース。
Azure DocumentDB
Microsoftが正式に4月8日アズールDocumentDBを立ち上げ番目、2015年、そしてそれは確かに典型的なのNoSQLの文書データベースとして特徴付けることができます。非常にスケーラブルで、スキーマフリーのJSONドキュメントで動作します。
DocumentDBは、最新のモバイルおよびWebアプリケーション向けに設計された真のスキーマフリーのNoSQLドキュメントデータベースサービスです。
また、一貫して高速な読み取りと書き込み、スキーマの柔軟性、およびデータベースをオンデマンドで簡単にスケールアップおよびスケールダウンする機能も提供します。
インデックスを作成するJSONドキュメントのスキーマを想定または必要としません。
DocumentDBは、ドキュメントがデータベースに追加されるとすぐに、ドキュメント内のすべてのプロパティに自動的にインデックスを付けます。
DocumentDBは、SQL言語を使用した複雑なアドホッククエリを可能にし、すべてのドキュメントは作成された瞬間に即座にクエリ可能であり、ドキュメント階層内の任意のプロパティを検索できます。
DocumentDB –価格
DocumentDBは、データベースアカウントに含まれるコレクションの数に基づいて請求されます。各アカウントには1つ以上のデータベースを含めることができ、各データベースには事実上無制限の数のコレクションを含めることができますが、初期のデフォルトのクォータは100です。このクォータは、Azureサポートに連絡することで解除できます。
コレクションはスケールの単位であるだけでなく、コストの単位でもあるため、DocumentDBでは、最大10GBのストレージ容量を持つコレクションごとに支払います。
データベースにドキュメントを格納するには、少なくとも1つのS1コレクションが必要です。これは月額約25ドルで、Azureサブスクリプションに対して請求されます。
データベースのサイズが大きくなり、10 GBを超えると、追加のデータを含めるために別のコレクションを購入する必要があります。
各S1コレクションは1秒あたり250リクエストユニットを提供します。それでも不十分な場合は、コレクションをS2にスケールアップして、1秒あたり1000リクエストユニットを月額約50ドルで取得できます。
また、S3まで上げて、月に約100ドル支払うこともできます。
DocumentDBは、いくつかの非常にユニークな機能で際立っています。Azure DocumentDBには、次の主要な機能と利点があります。
スキーマフリー
リレーショナルデータベースでは、すべてのテーブルに、テーブルの各行が準拠する必要のある列とデータ型を定義するスキーマがあります。
対照的に、ドキュメントデータベースには定義されたスキーマがなく、すべてのドキュメントは異なる構造にすることができます。
SQL構文
DocumentDBは、SQL言語を使用した複雑なアドホッククエリを可能にし、すべてのドキュメントは作成された瞬間に即座にクエリ可能です。ドキュメント階層内の任意の場所で任意のプロパティを検索できます。
調整可能な一貫性
これは、いくつかのきめ細かく明確に定義された整合性レベルを提供します。これにより、整合性、可用性、および待ち時間の間で適切なトレードオフを行うことができます。
明確に定義された4つの整合性レベルから選択して、整合性とパフォーマンスの間の最適なトレードオフを実現できます。クエリと読み取り操作の場合、DocumentDBは4つの異なる一貫性レベルを提供します-
- Strong
- Bounded-staleness
- Session
- Eventual
弾性スケール
スケーラビリティはNoSQLを使用したゲームの名前であり、DocumentDBが提供します。DocumentDBはすでにその規模が証明されています。
Office OneNoteやXboxなどの主要なサービスは、数十テラバイトのJSONドキュメントを含むデータベース、100万人を超えるアクティブユーザー、99.95%の可用性で一貫して動作するDocumentDBによってすでにサポートされています。
アプリケーションの成長に合わせてユニットを追加することで、予測可能なパフォーマンスでDocumentDBを柔軟にスケーリングできます。
完全に管理
DocumentDBは、Azureで実行されるサービスとして、フルマネージドのクラウドベースのプラットフォームとして利用できます。
インストールまたは管理するものは何もありません。
サーバー、ケーブル、処理するオペレーティングシステムやアップデート、セットアップするレプリカはありません。
マイクロソフトはそのすべての作業を行い、サービスを実行し続けます。
文字通り数分以内に、ブラウザーとAzureサブスクリプションだけを使用してDocumentDBの操作を開始できます。
Microsoftは、SQLServerも含む無料バージョンのVisualStudioを提供しており、そこからダウンロードできます。 https://www.visualstudio.com
インストール
Step 1−ダウンロードが完了したら、インストーラーを実行します。次のダイアログが表示されます。
Step 2 − [インストール]ボタンをクリックすると、インストールプロセスが開始されます。
Step 3 −インストールプロセスが正常に完了すると、次のダイアログが表示されます。
Step 4 −このダイアログを閉じ、必要に応じてコンピュータを再起動します。
Step 5−スタートメニューからVisual Studioを開き、以下のダイアログを開きます。準備のためだけに初めて時間がかかります。
すべてが完了すると、VisualStudioのメインウィンドウが表示されます。
Step 6 −「ファイル」→「新規」→「プロジェクト」から新しいプロジェクトを作成しましょう。
Step 7 − [コンソールアプリケーション]を選択し、[名前]フィールドにDocumentDBDemoと入力して、[OK]ボタンをクリックします。
Step 8 −ソリューションエクスプローラーで、プロジェクトを右クリックします。
Step 9 − [NuGetパッケージの管理]を選択すると、Visual Studioで次のウィンドウが開き、[オンラインで検索]入力ボックスでDocumentDBクライアントライブラリを検索します。
Step 10 −インストールボタンをクリックして最新バージョンをインストールします。
Step 11−「同意する」をクリックします。インストールが完了すると、出力ウィンドウにメッセージが表示されます。
これで、アプリケーションを開始する準備が整いました。
Microsoft Azure DocumentDBを使用するには、DocumentDBアカウントを作成する必要があります。この章では、Azureポータルを使用してDocumentDBアカウントを作成します。
Step 1 −オンラインにログインする https://portal.azure.com 既にAzureサブスクリプションをお持ちの場合は、最初にサインインする必要があります。
メインダッシュボードが表示されます。完全にカスタマイズ可能であるため、これらのタイルを好きなように配置したり、サイズを変更したり、頻繁に使用するものや使用しなくなったものに合わせてタイルを追加および削除したりできます。
Step 2 −ページの左上にある[新規]オプションを選択します。
Step 3 −ここで、[データ+ストレージ]> [Azure DocumentDB]オプションを選択すると、次の[新しいDocumentDBアカウント]セクションが表示されます。
グローバルに一意の名前(ID)を考え出す必要があります。これは、.documents.azure.comと組み合わせて、DocumentDBアカウントへのパブリックアドレス可能なエンドポイントです。そのアカウントの下に作成するすべてのデータベースには、このエンドポイントを使用してインターネット経由でアクセスできます。
Step 4 − azuredocdbdemoという名前を付けて、[リソースグループ]→[new_resource]をクリックします。
Step 5−場所、つまり、このアカウントをホストするMicrosoftデータセンターを選択します。場所を選択し、地域を選択します。
Step 6 − [ダッシュボードに固定]チェックボックスをオンにして、先に進み、[作成]ボタンをクリックします。
タイルがダッシュボードにすでに追加されていることがわかります。これにより、アカウントが作成されていることがわかります。DocumentDBがエンドポイントを割り当て、レプリカをプロビジョニングし、その他の作業をバックグラウンドで実行している間、新しいアカウントの設定には実際には数分かかる場合があります。
完了すると、ダッシュボードが表示されます。
Step 7 −作成したDocumentDBアカウントをクリックすると、次の画像のような詳細画面が表示されます。
DocumentDBに対してプログラミングを開始するとき、最初のステップは接続することです。したがって、DocumentDBアカウントに接続するには、2つのことが必要になります。
- Endpoint
- 認証キー
終点
エンドポイントはDocumentDBアカウントへのURLであり、DocumentDBアカウント名と.documents.azure.comを組み合わせて作成されます。ダッシュボードに行きましょう。
次に、作成したDocumentDBアカウントをクリックします。次の画像に示すような詳細が表示されます。
[キー]オプションを選択すると、次の図に示すように追加情報が表示されます。エンドポイントとして使用できるDocumentDBアカウントへのURLも表示されます。
認証キー
認証キーには資格情報が含まれており、2種類のキーがあります。マスターキーはアカウント内のすべてのリソースへのフルアクセスを許可し、リソーストークンは特定のリソースへの制限付きアクセスを許可します。
マスターキー
マスターキーでできないことは何もありません。必要に応じて、マスターキーを使用してデータベース全体を吹き飛ばすことができます。
このため、マスターキーを共有したり、クライアント環境に配布したりすることは絶対に避けてください。追加のセキュリティ対策として、頻繁に変更することをお勧めします。
上記のスクリーンショットで強調表示されているように、実際には、データベースアカウントごとにプライマリキーとセカンダリキーの2つのマスターキーがあります。
リソーストークン
マスターキーの代わりにリソーストークンを使用することもできます。
リソーストークンに基づく接続は、トークンで指定されたリソースにのみアクセスでき、他のリソースにはアクセスできません。
リソーストークンはユーザー権限に基づいているため、最初に1人以上のユーザーを作成し、これらはデータベースレベルで定義されます。
各ユーザーにアクセスを許可するリソースに基づいて、ユーザーごとに1つ以上のアクセス許可を作成します。
各権限は、特定のリソースへの読み取り専用またはフルアクセスのいずれかを許可し、データベース内の任意のユーザーリソースにすることができるリソーストークンを生成します。
第3章で作成したコンソールアプリケーションに行きましょう。
Step 1 −Program.csファイルに次の参照を追加します。
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;
Step 2−ここでエンドポイントURLと認証キーを追加します。この例では、主キーを認証キーとして使用します。
あなたの場合、エンドポイントURLと認証キーの両方が異なっている必要があることに注意してください。
private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
private const string AuthorizationKey =
"BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
Step 3 − CreateDocumentClientと呼ばれる非同期タスクでDocumentClientの新しいインスタンスを作成し、新しいDocumentClientをインスタンス化します。
Step 4 −Mainメソッドから非同期タスクを呼び出します。
以下は、これまでの完全なProgram.csファイルです。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;
namespace DocumentDBDemo {
class Program {
private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
private const string AuthorizationKey = "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/
StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
static void Main(string[] args) {
try {
CreateDocumentClient().Wait();
} catch (Exception e) {
Exception baseException = e.GetBaseException();
Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
}
Console.ReadKey();
}
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey);
}
}
}
この章では、DocumentDBアカウントに接続し、DocumentClientクラスのインスタンスを作成する方法を学習しました。
この章では、データベースの作成方法を学習します。Microsoft Azure DocumentDBを使用するには、DocumentDBアカウント、データベース、コレクション、およびドキュメントが必要です。すでにDocumentDBアカウントを持っていますが、データベースを作成するには2つのオプションがあります-
- MicrosoftAzureポータルまたは
- .Net SDK
MicrosoftAzureポータルを使用してDocumentDBのデータベースを作成する
ポータルを使用してデータベースを作成するには、次の手順に従います。
Step 1 − Azureポータルにログインすると、ダッシュボードが表示されます。
Step 2 −作成したDocumentDBアカウントをクリックすると、次のスクリーンショットに示すような詳細が表示されます。
Step 3 − [データベースの追加]オプションを選択し、データベースのIDを入力します。
Step 4 − [OK]をクリックします。
データベースが追加されていることがわかります。現時点ではコレクションはありませんが、JSONドキュメントを格納するコンテナーであるコレクションを後で追加できます。IDとリソースIDの両方があることに注意してください。
.NetSDKを使用してDocumentDBのデータベースを作成する
.Net SDKを使用してデータベースを作成するには、次の手順に従います。
Step 1 −前の章のVisualStudioでコンソールアプリケーションを開きます。
Step 2−新しいデータベースオブジェクトを作成して、新しいデータベースを作成します。新しいデータベースを作成するには、CreateDatabaseタスクで「mynewdb」に設定しているIdプロパティを割り当てるだけです。
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−このdatabaseDefinitionをCreateDatabaseAsyncに渡し、Resourceプロパティを使用して結果を取得します。すべてのcreateobjectメソッドは、作成されたアイテム(この場合はデータベース)を説明するResourceプロパティを返します。
Resourceプロパティから新しいデータベースオブジェクトを取得し、DocumentDBが割り当てたリソースIDとともにコンソールに表示されます。
Step 4 − DocumentClientがインスタンス化された後、CreateDocumentClientタスクからCreateDatabaseタスクを呼び出します。
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
await CreateDatabase(client);
}
以下は、これまでの完全なProgram.csファイルです。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;
namespace DocumentDBDemo {
class Program {
private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
private const string AuthorizationKey = "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/
StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
static void Main(string[] args) {
try {
CreateDocumentClient().Wait();
} catch (Exception e) {
Exception baseException = e.GetBaseException();
Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
}
Console.ReadKey();
}
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
await CreateDatabase(client);
}
}
private async static Task CreateDatabase(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("******** Create Database *******");
var databaseDefinition = new Database { Id = "mynewdb" };
var result = await client.CreateDatabaseAsync(databaseDefinition);
var database = result.Resource;
Console.WriteLine(" Database Id: {0}; Rid: {1}", database.Id, database.ResourceId);
Console.WriteLine("******** Database Created *******");
}
}
}
上記のコードをコンパイルして実行すると、データベースIDとリソースIDを含む次の出力が表示されます。
******** Create Database *******
Database Id: mynewdb; Rid: ltpJAA==
******** Database Created *******
これまで、DocumentDBアカウントに2つのデータベースを作成しました。最初のデータベースはAzureポータルを使用して作成され、2番目のデータベースは.NetSDKを使用して作成されます。これらのデータベースを表示するには、Azureポータルを使用できます。
AzureポータルでDocumentDBアカウントに移動すると、2つのデータベースが表示されます。
.Net SDKを使用して、コードからデータベースを表示または一覧表示することもできます。以下は、関連する手順です。
Step 1 −完全なリストを返すパラメータなしでデータベースクエリを発行しますが、クエリを渡して特定のデータベースまたは特定のデータベースを検索することもできます。
private static void GetDatabases(DocumentClient client) {
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("******** Get Databases List ********");
var databases = client.CreateDatabaseQuery().ToList();
foreach (var database in databases) {
Console.WriteLine(" Database Id: {0}; Rid: {1}", database.Id, database.ResourceId);
}
Console.WriteLine();
Console.WriteLine("Total databases: {0}", databases.Count);
}
コレクション、ドキュメント、ユーザー、その他のリソースを見つけるためのこれらのCreateQueryメソッドがたくさんあることがわかります。これらのメソッドは実際にはクエリを実行せず、クエリを定義して反復可能なオブジェクトを返すだけです。
実際にクエリを実行し、結果を繰り返し、リストに返すのはToList()の呼び出しです。
Step 2 − DocumentClientがインスタンス化された後、CreateDocumentClientタスクからGetDatabasesメソッドを呼び出します。
Step 3 − CreateDatabaseタスクにコメントするか、データベースIDを変更する必要もあります。そうしないと、データベースが存在するというエラーメッセージが表示されます。
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
//await CreateDatabase(client);
GetDatabases(client);
}
以下は、これまでの完全なProgram.csファイルです。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;
namespace DocumentDBDemo {
class Program {
private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
private const string AuthorizationKey = "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/
StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
static void Main(string[] args) {
try {
CreateDocumentClient().Wait();
} catch (Exception e) {
Exception baseException = e.GetBaseException();
Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
}
Console.ReadKey();
}
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
await CreateDatabase(client);
GetDatabases(client);
}
}
private async static Task CreateDatabase(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("******** Create Database *******");
var databaseDefinition = new Database { Id = "mynewdb" };
var result = await client.CreateDatabaseAsync(databaseDefinition);
var database = result.Resource;
Console.WriteLine(" Database Id: {0}; Rid: {1}", database.Id, database.ResourceId);
Console.WriteLine("******** Database Created *******");
}
private static void GetDatabases(DocumentClient client) {
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("******** Get Databases List ********");
var databases = client.CreateDatabaseQuery().ToList();
foreach (var database in databases) {
Console.WriteLine(" Database Id: {0}; Rid: {1}",
database.Id, database.ResourceId);
}
Console.WriteLine();
Console.WriteLine("Total databases: {0}", databases.Count);
}
}
}
上記のコードをコンパイルして実行すると、両方のデータベースのデータベースIDとリソースIDを含む次の出力が表示されます。最後に、データベースの総数も表示されます。
******** Get Databases List ********
Database Id: myfirstdb; Rid: Ic8LAA==
Database Id: mynewdb; Rid: ltpJAA==
Total databases: 2
.Net SDKを使用して、ポータルおよびコードから1つまたは複数のデータベースを削除できます。ここでは、DocumentDBにデータベースをドロップする方法を段階的に説明します。
Step 1−AzureポータルでDocumentDBアカウントに移動します。デモの目的で、次のスクリーンショットに示すように、さらに2つのデータベースを追加しました。
Step 2−データベースを削除するには、そのデータベースをクリックする必要があります。tempdbを選択しましょう。次のページが表示されたら、[データベースの削除]オプションを選択します。
Step 3 −確認メッセージが表示されますので、「はい」ボタンをクリックしてください。
ダッシュボードでtempdbが使用できなくなっていることがわかります。
.Net SDKを使用して、コードからデータベースを削除することもできます。次の手順を実行します。
Step 1 −削除したいデータベースのIDを指定してデータベースを削除しましょう。ただし、SelfLinkが必要です。
Step 2 −以前と同じようにCreateDatabaseQueryを呼び出していますが、今回は実際には、IDtempdb1のデータベースを1つだけ返すクエリを提供しています。
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−今回は、実際にはリストオブジェクトが必要ないため、ToList()の代わりにAsEnumerableを呼び出すことができます。結果のみを期待して、First()を使用したクエリによって返される最初のデータベースオブジェクトを取得するには、AsEnumerableを呼び出すだけで十分です。これはtempdb1のデータベースオブジェクトであり、データベースを削除するDeleteDatabaseAsyncを呼び出すために使用できるSelfLinkがあります。
Step 4 − DocumentClientがインスタンス化された後、CreateDocumentClientタスクからDeleteDatabaseタスクを呼び出す必要もあります。
Step 5 −指定したデータベースを削除した後にデータベースのリストを表示するには、GetDatabasesメソッドを再度呼び出します。
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
//await CreateDatabase(client);
GetDatabases(client);
await DeleteDatabase(client);
GetDatabases(client);
}
以下は、これまでの完全なProgram.csファイルです。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;
namespace DocumentDBDemo {
class Program {
private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
private const string AuthorizationKey = "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/
StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
static void Main(string[] args) {
try {
CreateDocumentClient().Wait();
} catch (Exception e) {
Exception baseException = e.GetBaseException();
Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
}
Console.ReadKey();
}
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
//await CreateDatabase(client);
GetDatabases(client);
await DeleteDatabase(client);
GetDatabases(client);
}
}
private async static Task CreateDatabase(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("******** Create Database *******");
var databaseDefinition = new Database { Id = "mynewdb" };
var result = await client.CreateDatabaseAsync(databaseDefinition);
var database = result.Resource;
Console.WriteLine(" Database Id: {0}; Rid: {1}",
database.Id, database.ResourceId);
Console.WriteLine("******** Database Created *******");
}
private static void GetDatabases(DocumentClient client) {
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("******** Get Databases List ********");
var databases = client.CreateDatabaseQuery().ToList();
foreach (var database in databases) {
Console.WriteLine(" Database Id: {0}; Rid: {1}", database.Id,
database.ResourceId);
}
Console.WriteLine();
Console.WriteLine("Total databases: {0}", databases.Count);
}
private async static Task DeleteDatabase(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("******** Delete Database ********");
Database database = client
.CreateDatabaseQuery("SELECT * FROM c WHERE c.id = 'tempdb1'")
.AsEnumerable()
.First();
await client.DeleteDatabaseAsync(database.SelfLink);
}
}
}
上記のコードをコンパイルして実行すると、3つのデータベースのデータベースIDとリソースID、およびデータベースの総数を含む次の出力が表示されます。
******** Get Databases List ********
Database Id: myfirstdb; Rid: Ic8LAA==
Database Id: mynewdb; Rid: ltpJAA==
Database Id: tempdb1; Rid: 06JjAA==
Total databases: 3
******** Delete Database ********
******** Get Databases List ********
Database Id: myfirstdb; Rid: Ic8LAA==
Database Id: mynewdb; Rid: ltpJAA==
Total databases: 2
データベースを削除した後、DocumentDBアカウントに残っているデータベースは2つだけであることが最後に表示されます。
この章では、コレクションの作成方法を学習します。これは、データベースの作成に似ています。コレクションは、ポータルから、または.NetSDKを使用するコードから作成できます。
Step 1 −Azureポータルのメインダッシュボードに移動します。
Step 2 −データベースリストからmyfirstdbを選択します。
Step 3− [コレクションの追加]オプションをクリックして、コレクションのIDを指定します。別のオプションの価格階層を選択します。
Step 4 − S1 Standardを選択し、[選択]→[OK]ボタンをクリックします。
ご覧のとおり、MyCollectionがmyfirstdbに追加されています。
.Net SDKを使用して、コードからコレクションを作成することもできます。コードからコレクションを追加するための次の手順を見てみましょう。
Step 1 − VisualStudioでコンソールアプリケーションを開きます。
Step 2 −コレクションを作成するには、最初にCreateDocumentClientタスクでIDによって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();
await CreateCollection(client, "MyCollection1");
await CreateCollection(client, "MyCollection2", "S2");
}
}
以下は、CreateCollectionタスクの実装です。
private async static Task CreateCollection(DocumentClient client, string collectionId,
string offerType = "S1") {
Console.WriteLine();
Console.WriteLine("**** Create Collection {0} in {1} ****", collectionId, database.Id);
var collectionDefinition = new DocumentCollection { Id = collectionId };
var options = new RequestOptions { OfferType = offerType };
var result = await client.CreateDocumentCollectionAsync(database.SelfLink,
collectionDefinition, options);
var collection = result.Resource;
Console.WriteLine("Created new collection");
ViewCollection(collection);
}
CreateDocumentCollectionAsyncメソッドに必要なIDを使用して新しいコレクションを定義する新しいDocumentCollectionオブジェクトを作成します。このオブジェクトは、offerTypeと呼ばれる新しいコレクションのパフォーマンス層を設定するためにここで使用しているオプションパラメーターも受け入れます。
これはデフォルトでS1になり、offerTypeを渡さなかったため、MyCollection1の場合はS1コレクションになり、MyCollection2の場合はS2を渡して、上記のようにこれをS2にします。
以下は、ViewCollectionメソッドの実装です。
private static void ViewCollection(DocumentCollection collection) {
Console.WriteLine("Collection ID: {0} ", collection.Id);
Console.WriteLine("Resource ID: {0} ", collection.ResourceId);
Console.WriteLine("Self Link: {0} ", collection.SelfLink);
Console.WriteLine("Documents Link: {0} ", collection.DocumentsLink);
Console.WriteLine("UDFs Link: {0} ", collection.UserDefinedFunctionsLink);
Console.WriteLine(" StoredProcs Link: {0} ", collection.StoredProceduresLink);
Console.WriteLine("Triggers Link: {0} ", collection.TriggersLink);
Console.WriteLine("Timestamp: {0} ", collection.Timestamp);
}
以下は、コレクション用のprogram.csファイルの完全な実装です。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;
namespace DocumentDBDemo {
class Program {
private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
private const string AuthorizationKey = "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/
StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
private static Database database;
static void Main(string[] args) {
try {
CreateDocumentClient().Wait();
} catch (Exception e) {
Exception baseException = e.GetBaseException();
Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
}
Console.ReadKey();
}
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
'myfirstdb'").AsEnumerable().First();
await CreateCollection(client, "MyCollection1");
await CreateCollection(client, "MyCollection2", "S2");
//await CreateDatabase(client);
//GetDatabases(client);
//await DeleteDatabase(client);
//GetDatabases(client);
}
}
private async static Task CreateCollection(DocumentClient client,
string collectionId, string offerType = "S1") {
Console.WriteLine();
Console.WriteLine("**** Create Collection {0} in {1} ****", collectionId,
database.Id);
var collectionDefinition = new DocumentCollection { Id = collectionId };
var options = new RequestOptions { OfferType = offerType };
var result = await
client.CreateDocumentCollectionAsync(database.SelfLink,
collectionDefinition, options);
var collection = result.Resource;
Console.WriteLine("Created new collection");
ViewCollection(collection);
}
private static void ViewCollection(DocumentCollection collection) {
Console.WriteLine("Collection ID: {0} ", collection.Id);
Console.WriteLine("Resource ID: {0} ", collection.ResourceId);
Console.WriteLine("Self Link: {0} ", collection.SelfLink);
Console.WriteLine("Documents Link: {0} ", collection.DocumentsLink);
Console.WriteLine("UDFs Link: {0} ", collection.UserDefinedFunctionsLink);
Console.WriteLine("StoredProcs Link: {0} ", collection.StoredProceduresLink);
Console.WriteLine("Triggers Link: {0} ", collection.TriggersLink);
Console.WriteLine("Timestamp: {0} ", collection.Timestamp);
}
}
}
上記のコードをコンパイルして実行すると、収集に関連するすべての情報を含む次の出力が表示されます。
**** Create Collection MyCollection1 in myfirstdb ****
Created new collection
Collection ID: MyCollection1
Resource ID: Ic8LAPPvnAA=
Self Link: dbs/Ic8LAA==/colls/Ic8LAPPvnAA=/
Documents Link: dbs/Ic8LAA==/colls/Ic8LAPPvnAA=/docs/
UDFs Link: dbs/Ic8LAA==/colls/Ic8LAPPvnAA=/udfs/
StoredProcs Link: dbs/Ic8LAA==/colls/Ic8LAPPvnAA=/sprocs/
Triggers Link: dbs/Ic8LAA==/colls/Ic8LAPPvnAA=/triggers/
Timestamp: 12/10/2015 4:55:36 PM
**** Create Collection MyCollection2 in myfirstdb ****
Created new collection
Collection ID: MyCollection2
Resource ID: Ic8LAKGHDwE=
Self Link: dbs/Ic8LAA==/colls/Ic8LAKGHDwE=/
Documents Link: dbs/Ic8LAA==/colls/Ic8LAKGHDwE=/docs/
UDFs Link: dbs/Ic8LAA==/colls/Ic8LAKGHDwE=/udfs/
StoredProcs Link: dbs/Ic8LAA==/colls/Ic8LAKGHDwE=/sprocs/
Triggers Link: dbs/Ic8LAA==/colls/Ic8LAKGHDwE=/triggers/
Timestamp: 12/10/2015 4:55:38 PM
1つまたは複数のコレクションを削除するには、ポータルからだけでなく、.NetSDKを使用してコードからも同じことを行うことができます。
Step 1−AzureポータルでDocumentDBアカウントに移動します。デモの目的で、次のスクリーンショットに示すように、さらに2つのコレクションを追加しました。
Step 2−コレクションを削除するには、そのコレクションをクリックする必要があります。TempCollection1を選択しましょう。次のページが表示されたら、[コレクションの削除]オプションを選択します。
Step 3−確認メッセージを表示します。次に、[はい]ボタンをクリックします。
TempCollection1がダッシュボードで使用できなくなっていることがわかります。
.Net SDKを使用して、コードからコレクションを削除することもできます。これを行うには、次の手順に従います。
Step 1 −削除したいコレクションのIDを指定してコレクションを削除しましょう。
これは、リソースを削除するために必要なセルフリンクを取得するためのIDによるクエリの通常のパターンです。
private async static Task DeleteCollection(DocumentClient client, string collectionId) {
Console.WriteLine();
Console.WriteLine("**** Delete Collection {0} in {1} ****", collectionId, database.Id);
var query = new SqlQuerySpec {
QueryText = "SELECT * FROM c WHERE c.id = @id",
Parameters = new SqlParameterCollection {
new SqlParameter {
Name = "@id", Value = collectionId
}
}
};
DocumentCollection collection = client.CreateDocumentCollectionQuery(database.SelfLink,
query).AsEnumerable().First();
await client.DeleteDocumentCollectionAsync(collection.SelfLink);
Console.WriteLine("Deleted collection {0} from database {1}", collectionId,
database.Id);
}
ここでは、パラメーター化されたクエリを作成するための好ましい方法を示します。collectionIdをハードコーディングしていないため、このメソッドを使用して任意のコレクションを削除できます。このSqlQuerySpecのパラメーターのプロパティに割り当てられたこのSqlParameterCollectionでIdパラメーターが定義されているIdによって特定のコレクションをクエリしています。
次に、SDKは、collectionIdが埋め込まれたDocumentDBの最終的なクエリ文字列を作成する作業を行います。
Step 2 −クエリを実行し、そのSelfLinkを使用してCreateDocumentClientタスクからコレクションを削除します。
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
'myfirstdb'").AsEnumerable().First();
await DeleteCollection(client, "TempCollection");
}
}
以下は、Program.csファイルの完全な実装です。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using Newtonsoft.Json;
namespace DocumentDBDemo {
class Program {
private const string EndpointUrl = "https://azuredocdbdemo.documents.azure.com:443/";
private const string AuthorizationKey = "BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/
StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
private static Database database;
static void Main(string[] args) {
try {
CreateDocumentClient().Wait();
} catch (Exception e) {
Exception baseException = e.GetBaseException();
Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
}
Console.ReadKey();
}
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
'myfirstdb'").AsEnumerable().First();
await DeleteCollection(client, "TempCollection");
//await CreateCollection(client, "MyCollection1");
//await CreateCollection(client, "MyCollection2", "S2");
////await CreateDatabase(client);
//GetDatabases(client);
//await DeleteDatabase(client);
//GetDatabases(client);
}
}
private async static Task CreateCollection(DocumentClient client,
string collectionId, string offerType = "S1") {
Console.WriteLine();
Console.WriteLine("**** Create Collection {0} in {1} ****", collectionId,
database.Id);
var collectionDefinition = new DocumentCollection { Id = collectionId };
var options = new RequestOptions { OfferType = offerType };
var result = await client.CreateDocumentCollectionAsync(database.SelfLink,
collectionDefinition, options);
var collection = result.Resource;
Console.WriteLine("Created new collection");
ViewCollection(collection);
}
private static void ViewCollection(DocumentCollection collection) {
Console.WriteLine("Collection ID: {0} ", collection.Id);
Console.WriteLine("Resource ID: {0} ", collection.ResourceId);
Console.WriteLine("Self Link: {0} ", collection.SelfLink);
Console.WriteLine("Documents Link: {0} ", collection.DocumentsLink);
Console.WriteLine("UDFs Link: {0} ", collection.UserDefinedFunctionsLink);
Console.WriteLine("StoredProcs Link: {0} ", collection.StoredProceduresLink);
Console.WriteLine("Triggers Link: {0} ", collection.TriggersLink);
Console.WriteLine("Timestamp: {0} ", collection.Timestamp);
}
private async static Task DeleteCollection(DocumentClient client,
string collectionId) {
Console.WriteLine();
Console.WriteLine("**** Delete Collection {0} in {1} ****", collectionId,
database.Id);
var query = new SqlQuerySpec {
QueryText = "SELECT * FROM c WHERE c.id = @id", Parameters = new
SqlParameterCollection {
new SqlParameter {
Name = "@id", Value = collectionId
}
}
};
DocumentCollection collection = client.CreateDocumentCollectionQuery
(database.SelfLink, query).AsEnumerable().First();
await client.DeleteDocumentCollectionAsync(collection.SelfLink);
Console.WriteLine("Deleted collection {0} from database {1}", collectionId,
database.Id);
}
}
}
上記のコードをコンパイルして実行すると、次の出力が返されます。
**** Delete Collection TempCollection in myfirstdb ****
Deleted collection TempCollection from database myfirstdb
この章では、コレクション内の実際のドキュメントを操作します。Azureポータルまたは.NetSDKのいずれかを使用してドキュメントを作成できます。
AzurePortalを使用したドキュメントの作成
コレクションにドキュメントを追加するための次の手順を見てみましょう。
Step 1 −myfirstdbにS1価格帯の新しいコレクションファミリを追加します。
Step 2 −ファミリコレクションを選択し、[ドキュメントの作成]オプションをクリックして、[新しいドキュメント]ブレードを開きます。
これは、新しいドキュメントのJSONを入力できる単純なテキストエディタです。
Step 3 −これは生データ入力なので、最初のドキュメントを入力しましょう。
{
"id": "AndersenFamily",
"lastName": "Andersen",
"parents": [
{ "firstName": "Thomas", "relationship": "father" },
{ "firstName": "Mary Kay", "relationship": "mother" }
],
"children": [
{
"firstName": "Henriette Thaulow",
"gender": "female",
"grade": 5,
"pets": [ { "givenName": "Fluffy", "type": "Rabbit" } ]
}
],
"location": { "state": "WA", "county": "King", "city": "Seattle"},
"isRegistered": true
}
上記の文書を入力すると、次の画面が表示されます。
ドキュメントのIDを指定したことに注意してください。id値は常に必須であり、同じコレクション内の他のすべてのドキュメント間で一意である必要があります。省略した場合、DocumentDBはGUIDまたはグローバル一意識別子を使用して自動的に生成します。
IDは常に文字列であり、数値、日付、ブール値、または別のオブジェクトにすることはできません。また、255文字を超えることはできません。
また、必要なid、lastName、isRegisteredなど、いくつかの最上位プロパティを持つドキュメントの階層構造にも注目してください。ただし、ネストされたプロパティもあります。
たとえば、parentsプロパティは、角括弧で示されているようにJSON配列として提供されます。この例では配列に子が1つしかない場合でも、子用の別の配列もあります。
Step 4 − [保存]ボタンをクリックしてドキュメントを保存すると、最初のドキュメントが作成されます。
ご覧のとおり、JSONにはかなりの書式設定が適用されています。これにより、空白でインデントされた独自の行ですべてのプロパティが分割され、各プロパティのネストレベルが示されます。
ポータルにはドキュメントエクスプローラーが含まれているので、それを使用して、作成したばかりのドキュメントを取得しましょう。
Step 5−データベースとデータベース内のコレクションを選択して、そのコレクション内のドキュメントを表示します。現在、myfirstdbという名前のデータベースとFamiliesというコレクションが1つだけあり、どちらもドロップダウンで事前に選択されています。
デフォルトでは、ドキュメントエクスプローラーはコレクション内のドキュメントのフィルタリングされていないリストを表示しますが、IDによる特定のドキュメント、または部分的なIDのワイルドカード検索に基づく複数のドキュメントを検索することもできます。
これまでのところ、コレクションに含まれているドキュメントは1つだけであり、そのIDは次の画面AndersonFamilyに表示されます。
Step 6 − IDをクリックして、ドキュメントを表示します。
.NETSDKを使用したドキュメントの作成
ドキュメントは単なる別の種類のリソースであり、SDKを使用してリソースを処理する方法についてはすでに理解していることをご存知のとおりです。
ドキュメントと他のリソースの大きな違いの1つは、もちろん、スキーマがないことです。
したがって、多くのオプションがあります。当然、JSONオブジェクトグラフやJSONテキストの生の文字列を操作することもできますが、コンパイル時にクラスを定義せずに実行時にプロパティにバインドできる動的オブジェクトを使用することもできます。
また、実際のC#オブジェクト、または呼び出されたエンティティ(ビジネスドメインクラスの場合もあります)を操作することもできます。
.NetSDKを使用してドキュメントの作成を始めましょう。手順は次のとおりです。
Step 1 − DocumentClientをインスタンス化してから、myfirstdbデータベースをクエリしてから、MyCollectionコレクションをクエリします。このコレクションは、クラス全体でアクセスできるように、このプライベート変数コレクションに格納されます。
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
'myfirstdb'").AsEnumerable().First();
collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
"SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();
await CreateDocuments(client);
}
}
Step 2 −CreateDocumentsタスクでいくつかのドキュメントを作成します。
private async static Task CreateDocuments(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("**** Create Documents ****");
Console.WriteLine();
dynamic document1Definition = new {
name = "New Customer 1", address = new {
addressType = "Main Office",
addressLine1 = "123 Main Street",
location = new {
city = "Brooklyn", stateProvinceName = "New York"
}, postalCode = "11229", countryRegionName = "United States"
},
};
Document document1 = await CreateDocument(client, document1Definition);
Console.WriteLine("Created document {0} from dynamic object", document1.Id);
Console.WriteLine();
}
最初のドキュメントは、この動的オブジェクトから生成されます。これはJSONのように見えるかもしれませんが、もちろんそうではありません。これはC#コードであり、実際の.NETオブジェクトを作成していますが、クラス定義はありません。代わりに、プロパティはオブジェクトが初期化される方法から推測されます。
このドキュメントにはIdプロパティが指定されていないことに注意してください。
それでは、CreateDocumentを見てみましょう。データベースとコレクションを作成するために見たのと同じパターンのように見えます。
private async static Task<Document> CreateDocument(DocumentClient client,
object documentObject) {
var result = await client.CreateDocumentAsync(collection.SelfLink, documentObject);
var document = result.Resource;
Console.WriteLine("Created new document: {0}\r\n{1}", document.Id, document);
return result;
}
Step 3−今回は、ドキュメントを追加するコレクションのSelfLinkを指定してCreateDocumentAsyncを呼び出します。この場合、システムで生成されたプロパティを持つ新しいドキュメントを表すリソースプロパティを持つ応答が返されます。
Documentオブジェクトは、リソースから継承するSDKで定義されたクラスであるため、すべての共通のリソースプロパティがありますが、スキーマフリードキュメント自体を定義する動的プロパティも含まれています。
private async static Task CreateDocuments(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("**** Create Documents ****");
Console.WriteLine();
dynamic document1Definition = new {
name = "New Customer 1", address = new {
addressType = "Main Office",
addressLine1 = "123 Main Street",
location = new {
city = "Brooklyn", stateProvinceName = "New York"
}, postalCode = "11229", countryRegionName = "United States"
},
};
Document document1 = await CreateDocument(client, document1Definition);
Console.WriteLine("Created document {0} from dynamic object", document1.Id);
Console.WriteLine();
}
上記のコードをコンパイルして実行すると、次の出力が表示されます。
**** Create Documents ****
Created new document: 34e9873a-94c8-4720-9146-d63fb7840fad {
"name": "New Customer 1",
"address": {
"addressType": "Main Office",
"addressLine1": "123 Main Street",
"location": {
"city": "Brooklyn", "stateProvinceName": "New York"
},
"postalCode": "11229", "countryRegionName": "United States"
},
"id": "34e9873a-94c8-4720-9146-d63fb7840fad",
"_rid": "Ic8LAMEUVgACAAAAAAAAAA==",
"_ts": 1449812756,
"_self": "dbs/Ic8LAA==/colls/Ic8LAMEUVgA=/docs/Ic8LAMEUVgACAAAAAAAAAA==/",
"_etag": "\"00001000-0000-0000-0000-566a63140000\"",
"_attachments": "attachments/"
}
Created document 34e9873a-94c8-4720-9146-d63fb7840fad from dynamic object
ご覧のとおり、IDは提供されていませんが、DocumentDBが新しいドキュメント用にIDを生成しました。
DocumentDBでは、実際にSQLを使用してドキュメントをクエリするため、この章では、DocumentDBの特別なSQL構文を使用したクエリについて説明します。.NET開発を行っている場合でも、使用でき、LINQクエリから適切なSQLを生成できるLINQプロバイダーもあります。
ポータルを使用したドキュメントのクエリ
Azureポータルにはクエリエクスプローラーがあり、DocumentDBデータベースに対して任意のSQLクエリを実行できます。
クエリエクスプローラーを使用して、可能な限り単純なクエリから始めて、クエリ言語のさまざまな機能を示します。
Step 1 −データベースブレードで、クリックしてクエリエクスプローラーブレードを開きます。
クエリはコレクションのスコープ内で実行されるため、クエリエクスプローラーではこのドロップダウンでコレクションを選択できます。
Step 2 −ポータルを使用して以前に作成したFamiliesコレクションを選択します。
クエリエクスプローラーは、この単純なクエリSELECT * FROM cで開きます。これは、コレクションからすべてのドキュメントを取得するだけです。
Step 3− [クエリの実行]ボタンをクリックして、このクエリを実行します。次に、完全なドキュメントが結果ブレードに取得されていることがわかります。
.NetSDKを使用したドキュメントのクエリ
以下は、.NetSDKを使用していくつかのドキュメントクエリを実行する手順です。
この例では、追加したばかりの新しく作成されたドキュメントをクエリします。
Step 1 − CreateDocumentQueryを呼び出し、コレクションを渡して、SelfLinkとクエリテキストによってクエリを実行します。
private async static Task QueryDocumentsWithPaging(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("**** Query Documents (paged results) ****");
Console.WriteLine();
Console.WriteLine("Quering for all documents");
var sql = "SELECT * FROM c";
var query = client.CreateDocumentQuery(collection.SelfLink, sql).AsDocumentQuery();
while (query.HasMoreResults) {
var documents = await query.ExecuteNextAsync();
foreach (var document in documents) {
Console.WriteLine(" Id: {0}; Name: {1};", document.id, document.name);
}
}
Console.WriteLine();
}
このクエリはコレクション全体のすべてのドキュメントも返しますが、CreateDocumentQueryで.ToListを呼び出すことはありません。これにより、すべての結果を1行のコードでプルダウンするために必要な数のリクエストが発行されます。
Step 2 −代わりに、AsDocumentQueryを呼び出すと、このメソッドはHasMoreResultsプロパティを持つクエリオブジェクトを返します。
Step 3 − HasMoreResultsがtrueの場合、ExecuteNextAsyncを呼び出して次のチャンクを取得し、そのチャンクのすべてのコンテンツをダンプします。
Step 4−必要に応じて、SQLの代わりにLINQを使用してクエリを実行することもできます。ここでは、qでLINQクエリを定義しましたが、.ToListを実行するまで実行されません。
private static void QueryDocumentsWithLinq(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("**** Query Documents (LINQ) ****");
Console.WriteLine();
Console.WriteLine("Quering for US customers (LINQ)");
var q =
from d in client.CreateDocumentQuery<Customer>(collection.DocumentsLink)
where d.Address.CountryRegionName == " United States"
select new {
Id = d.Id,
Name = d.Name,
City = d.Address.Location.City
};
var documents = q.ToList();
Console.WriteLine("Found {0} UK customers", documents.Count);
foreach (var document in documents) {
var d = document as dynamic;
Console.WriteLine(" Id: {0}; Name: {1}; City: {2}", d.Id, d.Name, d.City);
}
Console.WriteLine();
}
SDKは、LINQクエリをDocumentDBのSQL構文に変換し、LINQ構文に基づいてSELECT句とWHERE句を生成します。
Step 5 −次に、CreateDocumentClientタスクから上記のクエリを呼び出します。
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
'myfirstdb'").AsEnumerable().First();
collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
"SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();
//await CreateDocuments(client);
await QueryDocumentsWithPaging(client);
QueryDocumentsWithLinq(client);
}
}
上記のコードを実行すると、次の出力が表示されます。
**** Query Documents (paged results) ****
Quering for all documents
Id: 7e9ad4fa-c432-4d1a-b120-58fd7113609f; Name: New Customer 1;
Id: 34e9873a-94c8-4720-9146-d63fb7840fad; Name: New Customer 1;
**** Query Documents (LINQ) ****
Quering for US customers (LINQ)
Found 2 UK customers
Id: 7e9ad4fa-c432-4d1a-b120-58fd7113609f; Name: New Customer 1; City: Brooklyn
Id: 34e9873a-94c8-4720-9146-d63fb7840fad; Name: New Customer 1; City: Brooklyn
この章では、ドキュメントを更新する方法を学習します。Azureポータルを使用すると、ドキュメントエクスプローラーでドキュメントを開き、テキストファイルのようにエディターでドキュメントを更新することで、ドキュメントを簡単に更新できます。
「保存」ボタンをクリックします。これで、.Net SDKを使用してドキュメントを変更する必要がある場合は、それを置き換えることができます。削除して再作成する必要はありません。面倒なだけでなく、リソースIDも変更されるため、ドキュメントを変更するだけの場合は変更したくありません。.Net SDKを使用してドキュメントを更新するには、次の手順を実行します。
次のReplaceDocumentsタスクを見てみましょう。ここでは、isNewプロパティがtrueであるドキュメントをクエリしますが、何もないため、何も取得しません。それでは、以前に追加した、名前がNewCustomerで始まるドキュメントを変更しましょう。
Step 1 −これらのドキュメントにisNewプロパティを追加し、その値をtrueに設定します。
private async static Task ReplaceDocuments(DocumentClient client) {
Console.WriteLine();
Console.WriteLine(">>> Replace Documents <<<");
Console.WriteLine();
Console.WriteLine("Quering for documents with 'isNew' flag");
var sql = "SELECT * FROM c WHERE c.isNew = true";
var documents = client.CreateDocumentQuery(collection.SelfLink, sql).ToList();
Console.WriteLine("Documents with 'isNew' flag: {0} ", documents.Count);
Console.WriteLine();
Console.WriteLine("Quering for documents to be updated");
sql = "SELECT * FROM c WHERE STARTSWITH(c.name, 'New Customer') = true";
documents = client.CreateDocumentQuery(collection.SelfLink, sql).ToList();
Console.WriteLine("Found {0} documents to be updated", documents.Count);
foreach (var document in documents) {
document.isNew = true;
var result = await client.ReplaceDocumentAsync(document._self, document);
var updatedDocument = result.Resource;
Console.WriteLine("Updated document 'isNew' flag: {0}", updatedDocument.isNew);
}
Console.WriteLine();
Console.WriteLine("Quering for documents with 'isNew' flag");
sql = "SELECT * FROM c WHERE c.isNew = true";
documents = client.CreateDocumentQuery(collection.SelfLink, sql).ToList();
Console.WriteLine("Documents with 'isNew' flag: {0}: ", documents.Count);
Console.WriteLine();
}
Step 2 −同じSTARTSWITHクエリを使用して更新するドキュメントを取得します。これにより、動的オブジェクトとしてここに返されるドキュメントが得られます。
Step 3 − isNewプロパティを添付し、ドキュメントごとにtrueに設定します。
Step 4 − ReplaceDocumentAsyncを呼び出し、更新されたドキュメントとともにドキュメントのSelfLinkを渡します。
これが機能したことを証明するために、isNewがtrueに等しいドキュメントをクエリします。CreateDocumentClientタスクから上記のクエリを呼び出しましょう。
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
'myfirstdb'").AsEnumerable().First();
collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
"SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();
//await CreateDocuments(client);
//QueryDocumentsWithSql(client);
//await QueryDocumentsWithPaging(client);
//QueryDocumentsWithLinq(client);
await ReplaceDocuments(client);
}
}
上記のコードをコンパイルして実行すると、次の出力が返されます。
**** Replace Documents ****
Quering for documents with 'isNew' flag
Documents with 'isNew' flag: 0
Quering for documents to be updated
Found 2 documents to be updated
Updated document ‘isNew’ flag: True
Updated document ‘isNew’ flag: True
Quering for documents with 'isNew' flag
Documents with 'isNew' flag: 2
この章では、DocumentDBアカウントからドキュメントを削除する方法を学習します。Azure Portalを使用すると、ドキュメントエクスプローラーでドキュメントを開き、[削除]オプションをクリックすることで、任意のドキュメントを簡単に削除できます。
確認メッセージが表示されます。[はい]ボタンを押すと、ドキュメントがDocumentDBアカウントで利用できなくなっていることがわかります。
ここで、.NetSDKを使用してドキュメントを削除する場合。
Step 1−これは、新しい各ドキュメントのセルフリンクを取得するために最初にクエリを実行する前に見たのと同じパターンです。ここではSELECT *を使用しません。これにより、ドキュメント全体が返されますが、これは不要です。
Step 2 −代わりに、リストでSelfLinkを選択し、SelfLinkごとにDeleteDocumentAsyncを1つずつ呼び出して、コレクションからドキュメントを削除します。
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 −次に、CreateDocumentClientタスクから上記のDeleteDocumentsを呼び出しましょう。
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
'myfirstdb'").AsEnumerable().First();
collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
"SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();
await DeleteDocuments(client);
}
}
上記のコードを実行すると、次の出力が表示されます。
***** Delete Documents *****
Quering for documents to be deleted
Found 2 documents to be deleted
Deleted 2 new customer documents
DocumentDBのようなスキーマフリーのデータベースを使用すると、データモデルへの変更を非常に簡単に受け入れることができますが、それでもデータについて考えるのに時間を費やす必要があります。
あなたにはたくさんの選択肢があります。当然、JSONオブジェクトグラフやJSONテキストの生の文字列を操作することもできますが、コンパイル時にクラスを定義せずに実行時にプロパティにバインドできる動的オブジェクトを使用することもできます。
また、実際のC#オブジェクト、または呼び出されたエンティティ(ビジネスドメインクラスの場合もあります)を操作することもできます。
関係
ドキュメントの階層構造を見てみましょう。必要なID、lastName、isRegisteredなど、いくつかのトップレベルプロパティがありますが、ネストされたプロパティもあります。
{
"id": "AndersenFamily",
"lastName": "Andersen",
"parents": [
{ "firstName": "Thomas", "relationship": "father" },
{ "firstName": "Mary Kay", "relationship": "mother" }
],
"children": [
{
"firstName": "Henriette Thaulow",
"gender": "female",
"grade": 5,
"pets": [ { "givenName": "Fluffy", "type": "Rabbit" } ]
}
],
"location": { "state": "WA", "county": "King", "city": "Seattle"},
"isRegistered": true
}
たとえば、parentsプロパティは、角括弧で示されているようにJSON配列として提供されます。
この例では配列に子が1つしかない場合でも、子用の別の配列もあります。したがって、これは、ドキュメント内の1対多の関係に相当するものをモデル化する方法です。
配列の各要素が単純な値または別の複雑なオブジェクト、さらには別の配列である可能性がある配列を使用するだけです。
したがって、1つのファミリに複数の親と複数の子を含めることができ、子オブジェクトを見ると、子とペットの間の1対多の関係のネストされた配列であるペットのプロパティがあります。
locationプロパティでは、州、郡、市の3つの関連プロパティを1つのオブジェクトに結合しています。
オブジェクトの配列を埋め込むのではなく、この方法でオブジェクトを埋め込むことは、リレーショナルデータベースの別々のテーブルにある2つの行の間に1対1の関係を持つことに似ています。
データの埋め込み
DocumentDBなどのドキュメントストアでデータのモデリングを開始するときは、エンティティをJSONで表される自己完結型のドキュメントとして扱うようにしてください。リレーショナルデータベースを使用する場合、常にデータを正規化します。
データの正規化には、通常、顧客などのエンティティを取得し、連絡先の詳細や住所などの目立たないデータに分割することが含まれます。
連絡先の詳細と住所をすべて含む顧客を読み取るには、JOINSを使用して、実行時にデータを効果的に集約する必要があります。
次に、ドキュメントデータベース内の自己完結型エンティティと同じデータをモデル化する方法を見てみましょう。
{
"id": "1",
"firstName": "Mark",
"lastName": "Upston",
"addresses": [
{
"line1": "232 Main Street",
"line2": "Unit 1",
"city": "Brooklyn",
"state": "NY",
"zip": 11229
}
],
"contactDetails": [
{"email": "[email protected]"},
{"phone": "+1 356 545-86455", "extension": 5555}
]
}
ご覧のとおり、顧客のすべての情報が単一のJSONドキュメントに埋め込まれている顧客レコードを非正規化しました。
NoSQLには無料のスキーマがあるため、連絡先の詳細とアドレスをさまざまな形式で追加することもできます。NoSQLでは、1回の読み取り操作でデータベースから顧客レコードを取得できます。同様に、レコードの更新も1回の書き込み操作です。
以下は、.NetSDKを使用してドキュメントを作成する手順です。
Step 1−DocumentClientをインスタンス化します。次に、myfirstdbデータベースをクエリし、MyCollectionコレクションもクエリします。MyCollectionコレクションは、クラス全体でアクセスできるように、このプライベート変数コレクションに格納されます。
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
'myfirstdb'").AsEnumerable().First();
collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
"SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();
await CreateDocuments(client);
}
}
Step 2 −CreateDocumentsタスクでいくつかのドキュメントを作成します。
private async static Task CreateDocuments(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("**** Create Documents ****");
Console.WriteLine();
dynamic document1Definition = new {
name = "New Customer 1", address = new {
addressType = "Main Office",
addressLine1 = "123 Main Street",
location = new {
city = "Brooklyn", stateProvinceName = "New York"
},
postalCode = "11229", countryRegionName = "United States"
},
};
Document document1 = await CreateDocument(client, document1Definition);
Console.WriteLine("Created document {0} from dynamic object", document1.Id);
Console.WriteLine();
}
最初のドキュメントは、この動的オブジェクトから生成されます。これはJSONのように見えるかもしれませんが、もちろんそうではありません。これはC#コードであり、実際の.NETオブジェクトを作成していますが、クラス定義はありません。代わりに、プロパティはオブジェクトが初期化される方法から推測されます。また、このドキュメントのIdプロパティが提供されていないことにも気付くでしょう。
Step 3 −次に、CreateDocumentを見てみましょう。これは、データベースとコレクションを作成するために見たのと同じパターンのように見えます。
private async static Task<Document> CreateDocument(DocumentClient client,
object documentObject) {
var result = await client.CreateDocumentAsync(collection.SelfLink, documentObject);
var document = result.Resource;
Console.WriteLine("Created new document: {0}\r\n{1}", document.Id, document);
return result;
}
Step 4−今回は、ドキュメントを追加するコレクションのSelfLinkを指定してCreateDocumentAsyncを呼び出します。この場合、システムで生成されたプロパティを持つ新しいドキュメントを表すリソースプロパティを持つ応答が返されます。
次のCreateDocumentsタスクでは、3つのドキュメントを作成しました。
最初のドキュメントでは、Documentオブジェクトはリソースから継承するSDKで定義されたクラスであるため、すべての共通リソースプロパティがありますが、スキーマフリードキュメント自体を定義する動的プロパティも含まれています。
private async static Task CreateDocuments(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("**** Create Documents ****");
Console.WriteLine();
dynamic document1Definition = new {
name = "New Customer 1", address = new {
addressType = "Main Office",
addressLine1 = "123 Main Street",
location = new {
city = "Brooklyn", stateProvinceName = "New York"
},
postalCode = "11229",
countryRegionName = "United States"
},
};
Document document1 = await CreateDocument(client, document1Definition);
Console.WriteLine("Created document {0} from dynamic object", document1.Id);
Console.WriteLine();
var document2Definition = @" {
""name"": ""New Customer 2"",
""address"": {
""addressType"": ""Main Office"",
""addressLine1"": ""123 Main Street"",
""location"": {
""city"": ""Brooklyn"", ""stateProvinceName"": ""New York""
},
""postalCode"": ""11229"",
""countryRegionName"": ""United States""
}
}";
Document document2 = await CreateDocument(client, document2Definition);
Console.WriteLine("Created document {0} from JSON string", document2.Id);
Console.WriteLine();
var document3Definition = new Customer {
Name = "New Customer 3",
Address = new Address {
AddressType = "Main Office",
AddressLine1 = "123 Main Street",
Location = new Location {
City = "Brooklyn", StateProvinceName = "New York"
},
PostalCode = "11229",
CountryRegionName = "United States"
},
};
Document document3 = await CreateDocument(client, document3Definition);
Console.WriteLine("Created document {0} from typed object", document3.Id);
Console.WriteLine();
}
この2番目のドキュメントは、生のJSON文字列でのみ機能します。次に、JavaScriptSerializerを使用して文字列をオブジェクトに逆シリアル化するCreateDocumentのオーバーロードにステップインし、最初のドキュメントの作成に使用したのと同じCreateDocumentメソッドに渡します。
3番目のドキュメントでは、アプリケーションで定義されているC#オブジェクトCustomerを使用しました。
この顧客を見てみましょう。Idとaddressプロパティがあり、addressはネストされたオブジェクトであり、locationを含む独自のプロパティがあります。これはさらに別のネストされたオブジェクトです。
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DocumentDBDemo {
public class Customer {
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
// Must be nullable, unless generating unique values for new customers on client
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "address")]
public Address Address { get; set; }
}
public class Address {
[JsonProperty(PropertyName = "addressType")]
public string AddressType { get; set; }
[JsonProperty(PropertyName = "addressLine1")]
public string AddressLine1 { get; set; }
[JsonProperty(PropertyName = "location")]
public Location Location { get; set; }
[JsonProperty(PropertyName = "postalCode")]
public string PostalCode { get; set; }
[JsonProperty(PropertyName = "countryRegionName")]
public string CountryRegionName { get; set; }
}
public class Location {
[JsonProperty(PropertyName = "city")]
public string City { get; set; }
[JsonProperty(PropertyName = "stateProvinceName")]
public string StateProvinceName { get; set; }
}
}
フェンスの両側で適切な規則を維持したいので、JSONプロパティ属性も用意しています。
そのため、ネストされた子オブジェクトとともにNew Customerオブジェクトを作成し、CreateDocumentをもう一度呼び出します。顧客オブジェクトにはIdプロパティがありますが、その値を指定しなかったため、DocumentDBは、前の2つのドキュメントの場合と同様に、GUIDに基づいてIDプロパティを生成しました。
上記のコードをコンパイルして実行すると、次の出力が表示されます。
**** 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またはJavaScriptObject Notationは、人間が読める形式のデータ交換用に設計された軽量のテキストベースのオープンスタンダードであり、マシンによる解析と生成も簡単です。JSONはDocumentDBの中心です。JSONをネットワーク経由で送信し、JSONをJSONとして保存し、JSONツリーにインデックスを付けて完全なJSONドキュメントでクエリを実行できるようにします。
JSON形式は次のデータ型をサポートします-
S.No. | タイプと説明 |
---|---|
1 | Number JavaScriptの倍精度浮動小数点形式 |
2 | String バックスラッシュをエスケープした二重引用符付きUnicode |
3 | Boolean 正しいか間違っているか |
4 | Array 順序付けられた値のシーケンス |
5 | Value 文字列、数値、trueまたはfalse、nullなどにすることができます。 |
6 | Object キーと値のペアの順序付けられていないコレクション |
7 | Whitespace トークンの任意のペア間で使用できます |
8 | Null 空の |
簡単なDateTime型の例を見てみましょう。顧客クラスに生年月日を追加します。
public class Customer {
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
// Must be nullable, unless generating unique values for new customers on client
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "address")]
public Address Address { get; set; }
[JsonProperty(PropertyName = "birthDate")]
public DateTime BirthDate { get; set; }
}
次のコードに示すように、DateTimeを使用して保存、取得、およびクエリを実行できます。
private async static Task CreateDocuments(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("**** Create Documents ****");
Console.WriteLine();
var document3Definition = new Customer {
Id = "1001",
Name = "Luke Andrew",
Address = new Address {
AddressType = "Main Office",
AddressLine1 = "123 Main Street",
Location = new Location {
City = "Brooklyn",
StateProvinceName = "New York"
},
PostalCode = "11229",
CountryRegionName = "United States"
},
BirthDate = DateTime.Parse(DateTime.Today.ToString()),
};
Document document3 = await CreateDocument(client, document3Definition);
Console.WriteLine("Created document {0} from typed object", document3.Id);
Console.WriteLine();
}
上記のコードをコンパイルして実行し、ドキュメントを作成すると、生年月日が追加されていることがわかります。
**** Create Documents ****
Created new document: 1001
{
"id": "1001",
"name": "Luke Andrew",
"address": {
"addressType": "Main Office",
"addressLine1": "123 Main Street",
"location": {
"city": "Brooklyn",
"stateProvinceName": "New York"
},
"postalCode": "11229",
"countryRegionName": "United States"
},
"birthDate": "2015-12-14T00:00:00",
"_rid": "Ic8LAMEUVgAKAAAAAAAAAA==",
"_ts": 1450113676,
"_self": "dbs/Ic8LAA==/colls/Ic8LAMEUVgA=/docs/Ic8LAMEUVgAKAAAAAAAAAA==/",
"_etag": "\"00002d00-0000-0000-0000-566efa8c0000\"",
"_attachments": "attachments/"
}
Created document 1001 from typed object
Microsoftは最近、SQL文法のTOPキーワードなど、Azure DocumentDBのクエリ方法にいくつかの改善を加えました。これにより、クエリの実行が速くなり、リソースの消費が少なくなり、クエリ演算子の制限が増え、追加のLINQ演算子のサポートが追加されました。 .NETSDK。
最初の2つのレコードのみを取得する簡単な例を見てみましょう。多数のレコードがあり、それらの一部のみを取得する場合は、Topキーワードを使用できます。この例では、地震の記録がたくさんあります。
ここで、最初の2つのレコードのみを表示します
Step 1 −クエリエクスプローラに移動し、このクエリを実行します。
SELECT * FROM c
WHERE c.magnitude > 2.5
TOPキーワードをまだ指定していないため、4つのレコードが取得されていることがわかります。
Step 2−同じクエリでTOPキーワードを使用します。ここでは、TOPキーワードを指定しました。「2」は、2つのレコードのみが必要であることを意味します。
SELECT TOP 2 * FROM c
WHERE c.magnitude > 2.5
Step 3 −このクエリを実行すると、2つのレコードのみが取得されていることがわかります。
同様に、.NetSDKを使用するコードでTOPキーワードを使用できます。以下は実装です。
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();
}
以下は、DocumentClientと地震データベースをインスタンス化する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 =
'earthquake'").AsEnumerable().First();
collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
"SELECT * FROM c WHERE c.id = 'earthquakedata'").AsEnumerable().First();
await QueryDocumentsWithPaging(client);
}
}
上記のコードをコンパイルして実行すると、3つのレコードのみが取得されていることがわかります。
**** Query Documents (paged results) ****
Quering for all documents
PublicId: 2015p947400; Magnitude: 2.515176918;
PublicId: 2015p947373; Magnitude: 1.506774108;
PublicId: 2015p947329; Magnitude: 1.593394461;
Microsoft Azure DocumentDBは、SQL overJSONドキュメントを使用したドキュメントのクエリをサポートしています。クエリでORDERBY句を使用して、コレクション内のドキュメントを数値と文字列で並べ替えることができます。この句には、オプションのASC / DESC引数を含めて、結果を取得する必要がある順序を指定できます。
JSONドキュメントがある次の例を見てみましょう。
{
"id": "Food Menu",
"description": "Grapes, red or green (European type, such as Thompson seedless), raw",
"tags": [
{
"name": "grapes"
},
{
"name": "red or green (european type"
},
{
"name": "such as thompson seedless)"
},
{
"name": "raw"
}
],
"foodGroup": "Fruits and Fruit Juices",
"servings": [
{
"amount": 1,
"description": "cup",
"weightInGrams": 151
},
{
"amount": 10,
"description": "grapes",
"weightInGrams": 49
},
{
"amount": 1,
"description": "NLEA serving",
"weightInGrams": 126
}
]
}
以下は、結果を降順でソートするためのSQLクエリです。
SELECT f.description, f.foodGroup,
f.servings[2].description AS servingDescription,
f.servings[2].weightInGrams AS servingWeight
FROM f
ORDER BY f.servings[2].weightInGrams DESC
上記のクエリを実行すると、次の出力が表示されます。
[
{
"description": "Grapes, red or green (European type, such as Thompson
seedless), raw",
"foodGroup": "Fruits and Fruit Juices",
"servingDescription": "NLEA serving",
"servingWeight": 126
}
]
デフォルトでは、DocumentDBは、ドキュメントがデータベースに追加されるとすぐに、ドキュメント内のすべてのプロパティに自動的にインデックスを付けます。ただし、インデックスを作成する必要のない特定のドキュメントやプロパティがある場合は、ストレージと処理のオーバーヘッドを削減する独自のインデックス作成ポリシーを制御および微調整できます。
DocumentDBにすべてのプロパティに自動的にインデックスを付けるように指示するデフォルトのインデックスポリシーは、多くの一般的なシナリオに適しています。ただし、インデックスを作成するものとインデックスを作成しないもの、およびインデックス作成に関するその他の機能を正確に制御するカスタムポリシーを実装することもできます。
DocumentDBは、次のタイプのインデックス作成をサポートしています-
- Hash
- Range
ハッシュ
ハッシュインデックスを使用すると、等しいかどうかを効率的にクエリできます。つまり、より小さい、より大きい、またはその間の値の範囲で一致するのではなく、特定のプロパティが正確な値に等しいドキュメントを検索します。
ハッシュインデックスを使用して範囲クエリを実行できますが、DocumentDBはハッシュインデックスを使用して一致するドキュメントを見つけることができず、代わりに各ドキュメントを順番にスキャンして、範囲クエリで選択する必要があるかどうかを判断する必要があります。
ハッシュインデックスのみを持つプロパティでORDERBY句を使用してドキュメントを並べ替えることはできません。
範囲
プロパティに定義された範囲インデックスであるDocumentDBを使用すると、値の範囲に対してドキュメントを効率的にクエリできます。また、ORDER BYを使用して、そのプロパティのクエリ結果を並べ替えることもできます。
DocumentDBを使用すると、任意またはすべてのプロパティでハッシュと範囲インデックスの両方を定義できます。これにより、効率的な等式クエリと範囲クエリ、およびORDERBYが可能になります。
インデックス作成ポリシー
すべてのコレクションには、すべてのドキュメントのすべてのプロパティの数値と文字列に使用されるインデックスのタイプを指定するインデックスポリシーがあります。
また、ドキュメントがコレクションに追加されるときに、ドキュメントが自動的にインデックスに登録されるかどうかを制御することもできます。
自動インデックス作成はデフォルトで有効になっていますが、ドキュメントを追加するときにその動作をオーバーライドして、特定のドキュメントにインデックスを付けないようにDocumentDBに指示することができます。
自動インデックス作成を無効にして、コレクションに追加されたときにデフォルトでドキュメントにインデックスが作成されないようにすることができます。同様に、これをドキュメントレベルで上書きし、コレクションに追加するときに特定のドキュメントにインデックスを付けるようにDocumentDBに指示できます。これは、手動インデックス付けとして知られています。
インデックスを含める/除外する
インデックス作成ポリシーでは、インデックスに含める、またはインデックスから除外するパスを定義することもできます。これは、クエリを実行することのないドキュメントの特定の部分と、クエリを実行する特定の部分があることがわかっている場合に役立ちます。
このような場合、コレクションに追加された各ドキュメントの特定の部分だけにインデックスを付けるようにDocumentDBに指示することで、インデックス作成のオーバーヘッドを減らすことができます。
自動インデックス作成
自動インデックス作成の簡単な例を見てみましょう。
Step 1 −最初に、自動インデックス作成と呼ばれるコレクションを作成します。ポリシーを明示的に指定せずに、このコレクションはデフォルトのインデックス作成ポリシーを使用します。つまり、このコレクションで自動インデックス作成が有効になります。
ここでは、データベースの自己リンクにIDベースのルーティングを使用しているため、コレクションを作成する前に、リソースIDを知ったりクエリを実行したりする必要はありません。mydbであるデータベースIDを使用できます。
Step 2 −次に、姓がUpstonの2つのドキュメントを作成しましょう。
private async static Task AutomaticIndexing(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("**** Override Automatic Indexing ****");
// Create collection with automatic indexing
var collectionDefinition = new DocumentCollection {
Id = "autoindexing"
};
var collection = await client.CreateDocumentCollectionAsync("dbs/mydb",
collectionDefinition);
// Add a document (indexed)
dynamic indexedDocumentDefinition = new {
id = "MARK",
firstName = "Mark",
lastName = "Upston",
addressLine = "123 Main Street",
city = "Brooklyn",
state = "New York",
zip = "11229",
};
Document indexedDocument = await client
.CreateDocumentAsync("dbs/mydb/colls/autoindexing", indexedDocumentDefinition);
// Add another document (request no indexing)
dynamic unindexedDocumentDefinition = new {
id = "JANE",
firstName = "Jane",
lastName = "Upston",
addressLine = "123 Main Street",
city = "Brooklyn",
state = "New York",
zip = "11229",
};
Document unindexedDocument = await client
.CreateDocumentAsync("dbs/mydb/colls/autoindexing", unindexedDocumentDefinition,
new RequestOptions { IndexingDirective = IndexingDirective.Exclude });
//Unindexed document won't get returned when querying on non-ID (or selflink) property
var doeDocs = client.CreateDocumentQuery("dbs/mydb/colls/autoindexing", "SELECT *
FROM c WHERE c.lastName = 'Doe'").ToList();
Console.WriteLine("Documents WHERE lastName = 'Doe': {0}", doeDocs.Count);
// Unindexed document will get returned when using no WHERE clause
var allDocs = client.CreateDocumentQuery("dbs/mydb/colls/autoindexing",
"SELECT * FROM c").ToList();
Console.WriteLine("All documents: {0}", allDocs.Count);
// Unindexed document will get returned when querying by ID (or self-link) property
Document janeDoc = client.CreateDocumentQuery("dbs/mydb/colls/autoindexing",
"SELECT * FROM c WHERE c.id = 'JANE'").AsEnumerable().FirstOrDefault();
Console.WriteLine("Unindexed document self-link: {0}", janeDoc.SelfLink);
// Delete the collection
await client.DeleteDocumentCollectionAsync("dbs/mydb/colls/autoindexing");
}
この最初のものは、Mark Upstonの場合、コレクションに追加され、デフォルトのインデックス付けポリシーに基づいてすぐに自動的にインデックス付けされます。
ただし、Mark Upstonの2番目のドキュメントが追加されると、コレクションのインデックス作成ポリシーにかかわらず、このドキュメントにインデックスを付けないようにDocumentDBに明示的に指示するIndexingDirective.Excludeを使用してリクエストオプションを渡しました。
最後に、両方のドキュメントに対してさまざまなタイプのクエリがあります。
Step 3 −CreateDocumentClientからAutomaticIndexingタスクを呼び出しましょう。
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
await AutomaticIndexing(client);
}
}
上記のコードをコンパイルして実行すると、次の出力が返されます。
**** Override Automatic Indexing ****
Documents WHERE lastName = 'Upston': 1
All documents: 2
Unindexed document self-link: dbs/kV5oAA==/colls/kV5oAOEkfQA=/docs/kV5oAOEkfQACA
AAAAAAAAA==/
ご覧のとおり、このようなドキュメントは2つありますが、Markのドキュメントにはインデックスが付けられていないため、クエリはMarkのドキュメントのみを返します。コレクション内のすべてのドキュメントを取得するためにWHERE句を指定せずに再度クエリを実行すると、両方のドキュメントを含む結果セットが得られます。これは、インデックス付けされていないドキュメントが、WHERE句のないクエリによって常に返されるためです。
IDまたはセルフリンクでインデックス付けされていないドキュメントを取得することもできます。したがって、MarkのドキュメントをID MARKでクエリすると、コレクションでインデックスが作成されていなくても、DocumentDBがドキュメントを返すことがわかります。
手動インデックス作成
自動インデックス作成をオーバーライドすることによる手動インデックス作成の簡単な例を見てみましょう。
Step 1−まず、manualindexingというコレクションを作成し、自動インデックス作成を明示的に無効にすることでデフォルトのポリシーを上書きします。これは、特に要求がない限り、このコレクションに追加された新しいドキュメントはインデックスに登録されないことを意味します。
private async static Task ManualIndexing(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("**** Manual Indexing ****");
// Create collection with manual indexing
var collectionDefinition = new DocumentCollection {
Id = "manualindexing",
IndexingPolicy = new IndexingPolicy {
Automatic = false,
},
};
var collection = await client.CreateDocumentCollectionAsync("dbs/mydb",
collectionDefinition);
// Add a document (unindexed)
dynamic unindexedDocumentDefinition = new {
id = "MARK",
firstName = "Mark",
lastName = "Doe",
addressLine = "123 Main Street",
city = "Brooklyn",
state = "New York",
zip = "11229",
};
Document unindexedDocument = await client
.CreateDocumentAsync("dbs/mydb/colls/manualindexing", unindexedDocumentDefinition);
// Add another document (request indexing)
dynamic indexedDocumentDefinition = new {
id = "JANE",
firstName = "Jane",
lastName = "Doe",
addressLine = "123 Main Street",
city = "Brooklyn",
state = "New York",
zip = "11229",
};
Document indexedDocument = await client.CreateDocumentAsync
("dbs/mydb/colls/manualindexing", indexedDocumentDefinition, new RequestOptions {
IndexingDirective = IndexingDirective.Include });
//Unindexed document won't get returned when querying on non-ID (or selflink) property
var doeDocs = client.CreateDocumentQuery("dbs/mydb/colls/manualindexing",
"SELECT * FROM c WHERE c.lastName = 'Doe'").ToList();
Console.WriteLine("Documents WHERE lastName = 'Doe': {0}", doeDocs.Count);
// Unindexed document will get returned when using no WHERE clause
var allDocs = client.CreateDocumentQuery("dbs/mydb/colls/manualindexing",
"SELECT * FROM c").ToList();
Console.WriteLine("All documents: {0}", allDocs.Count);
// Unindexed document will get returned when querying by ID (or self-link) property
Document markDoc = client
.CreateDocumentQuery("dbs/mydb/colls/manualindexing",
"SELECT * FROM c WHERE c.id = 'MARK'")
.AsEnumerable().FirstOrDefault();
Console.WriteLine("Unindexed document self-link: {0}", markDoc.SelfLink);
await client.DeleteDocumentCollectionAsync("dbs/mydb/colls/manualindexing");
}
Step 2−ここで、以前と同じ2つのドキュメントを再度作成します。コレクションのインデックス作成ポリシーにより、このドキュメントはインデックスに登録されないため、今回はMarkのドキュメントに特別なリクエストオプションを提供しません。
Step 3 − Markに2番目のドキュメントを追加するとき、IndexingDirective.IncludeでRequestOptionsを使用して、このドキュメントにインデックスを付ける必要があることをDocumentDBに通知します。これにより、コレクションのインデックス付けポリシーが上書きされます。
最後に、両方のドキュメントに対してさまざまなタイプのクエリがあります。
Step 4 −CreateDocumentClientからManualIndexingタスクを呼び出しましょう。
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
await ManualIndexing(client);
}
}
上記のコードをコンパイルして実行すると、次の出力が表示されます。
**** Manual Indexing ****
Documents WHERE lastName = 'Upston': 1
All documents: 2
Unindexed document self-link: dbs/kV5oAA==/colls/kV5oANHJPgE=/docs/kV5oANHJPgEBA
AAAAAAAAA==/
この場合も、クエリは2つのドキュメントのうち1つだけを返しますが、今回は、明示的にインデックスを作成するように要求したJaneDoeを返します。ただし、以前と同様に、WHERE句を指定せずにクエリを実行すると、Markのインデックス付けされていないドキュメントを含め、コレクション内のすべてのドキュメントが取得されます。IDでインデックス付けされていないドキュメントをクエリすることもできます。これは、インデックスが作成されていなくてもDocumentDBが返します。
マイクロソフトは追加しました geospatial support、ドキュメントに位置データを保存し、ポイントとポリゴン間の距離と交点の空間計算を実行できます。
空間データは、空間内のオブジェクトの位置と形状を表します。
通常、人の場所、関心のある場所、都市の境界、または湖を表すために使用できます。
一般的な使用例には、近接クエリが含まれることがよくあります。たとえば、「現在地の近くにあるすべての大学を検索する」などです。
A Point特定の大学の住所など、正確な場所を表す空間内の単一の位置を示します。ポイントは、その座標ペア(経度と緯度)を使用してDocumentDBで表されます。以下はJSONポイントの例です。
{
"type":"Point",
"coordinates":[ 28.3, -10.7 ]
}
大学の場所を含む簡単な例を見てみましょう。
{
"id":"case-university",
"name":"CASE: Center For Advanced Studies In Engineering",
"city":"Islamabad",
"location": {
"type":"Point",
"coordinates":[ 33.7194136, -73.0964862 ]
}
}
場所に基づいて大学名を取得するには、次のクエリを使用できます。
SELECT c.name FROM c
WHERE c.id = "case-university" AND ST_ISVALID({
"type":"Point",
"coordinates":[ 33.7194136, -73.0964862 ]})
上記のクエリを実行すると、次の出力が表示されます。
[
{
"name": "CASE: Center For Advanced Studies In Engineering"
}
]
.NETで地理空間データを使用してドキュメントを作成する
地理空間データを使用してドキュメントを作成できます。大学のドキュメントが作成される簡単な例を見てみましょう。
private async static Task CreateDocuments(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("**** Create Documents ****");
Console.WriteLine();
var uniDocument = new UniversityProfile {
Id = "nust",
Name = "National University of Sciences and Technology",
City = "Islamabad",
Loc = new Point(33.6455715, 72.9903447)
};
Document document = await CreateDocument(client, uniDocument);
Console.WriteLine("Created document {0} from typed object", document.Id);
Console.WriteLine();
}
以下は、UniversityProfileクラスの実装です。
public class UniversityProfile {
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("city")]
public string City { get; set; }
[JsonProperty("location")]
public Point Loc { get; set; }
}
上記のコードをコンパイルして実行すると、次の出力が返されます。
**** Create Documents ****
Created new document: nust
{
"id": "nust",
"name": "National University of Sciences and Technology",
"city": "Islamabad",
"location": {
"type": "Point",
"coordinates": [
33.6455715,
72.9903447
]
},
"_rid": "Ic8LAMEUVgANAAAAAAAAAA==",
"_ts": 1450200910,
"_self": "dbs/Ic8LAA==/colls/Ic8LAMEUVgA=/docs/Ic8LAMEUVgANAAAAAAAAAA==/",
"_etag": "\"00004100-0000-0000-0000-56704f4e0000\"",
"_attachments": "attachments/"
}
Created document nust from typed object
データベースが10GBを超えて大きくなり始めたら、新しいコレクションを作成し、データをますます多くのコレクションに分散または分割するだけでスケールアウトできます。
遅かれ早かれ、10GBの容量を持つ単一のコレクションでは、データベースを含めるのに十分ではありません。10GBはそれほど多くないように聞こえるかもしれませんが、JSONドキュメントを保存していることを忘れないでください。これは単なるプレーンテキストであり、インデックスのストレージオーバーヘッドを考慮しても、多くのプレーンテキストドキュメントを10GBに収めることができます。
スケーラビリティに関しては、ストレージだけが問題ではありません。コレクションで利用可能な最大スループットは、S3コレクションで得られる1秒あたり2.5千リクエストユニットです。したがって、より高いスループットが必要な場合は、複数のコレクションでパーティション化してスケールアウトする必要もあります。スケールアウトパーティショニングは、horizontal partitioning。
AzureDocumentDBを使用してデータをパーティション分割するために使用できるアプローチは多数あります。以下は最も一般的な戦略です-
- スピルオーバーパーティショニング
- 範囲分割
- ルックアップパーティショニング
- ハッシュ分割
スピルオーバーパーティショニング
パーティションキーがないため、波及分割は最も単純な戦略です。多くのことについて確信が持てない場合は、最初から始めることをお勧めします。単一のコレクションを超えてスケールアウトする必要があるかどうか、追加する必要のあるコレクションの数、またはそれらを追加する必要がある速度がわからない場合があります。
波及効果のパーティション分割は単一のコレクションから始まり、パーティションキーはありません。
コレクションは増加し始め、その後、10 GBの制限に近づき始めるまで、さらに増加します。
容量が90%に達すると、新しいコレクションに波及し、新しいドキュメントに使用し始めます。
データベースがより多くのコレクションにスケールアウトしたら、パーティションキーに基づく戦略に移行することをお勧めします。
その場合、移行先の戦略に基づいてドキュメントを別のコレクションに移動することにより、データのバランスを取り直す必要があります。
範囲分割
最も一般的な戦略の1つは、範囲の分割です。このアプローチでは、ドキュメントのパーティションキーが含まれる可能性のある値の範囲を決定し、その範囲に対応するコレクションにドキュメントを送信します。
日付は、定義された日付の範囲内にあるドキュメントを保持するコレクションを作成するこの戦略で非常に一般的に使用されます。十分に小さい範囲を定義する場合、コレクションが10GBの制限を超えることはないと確信できます。たとえば、1つのコレクションで1か月全体のドキュメントを合理的に処理できるシナリオがあります。
また、ほとんどのユーザーが現在のデータ(今月またはおそらく先月のデータ)を照会している場合もありますが、ユーザーがはるかに古いデータを検索することはめったにありません。したがって、6月にS3コレクションから始めます。これは、購入できる最も高価なコレクションであり、最高のスループットを実現します。
7月に別のS3コレクションを購入して7月のデータを保存し、6月のデータをより安価なS2コレクションにスケールダウンします。次に、8月に別のS3コレクションを取得し、7月をS2に、6月をS1にスケールダウンします。毎月、現在のデータを常に高スループットで利用できるようにし、古いデータを低スループットで利用できるようにします。
クエリがパーティションキーを提供する限り、クエリが必要なコレクションのみがクエリされ、スピルオーバーパーティションの場合のようにデータベース内のすべてのコレクションがクエリされるわけではありません。
ルックアップパーティショニング
ルックアップパーティションを使用すると、パーティションキーに基づいてドキュメントを特定のコレクションにルーティングするパーティションマップを定義できます。たとえば、地域ごとに分割できます。
すべての米国のドキュメントを1つのコレクションに、すべてのヨーロッパのドキュメントを別のコレクションに、他の地域のすべてのドキュメントを3番目のコレクションに保存します。
このパーティションマップを使用すると、ルックアップパーティションリゾルバーは、各ドキュメントに含まれる領域プロパティであるパーティションキーに基づいて、ドキュメントを作成するコレクションとクエリするコレクションを特定できます。
ハッシュ分割
ハッシュパーティショニングでは、ハッシュ関数の値に基づいてパーティションが割り当てられるため、リクエストとデータを複数のパーティションに均等に分散できます。
これは通常、多数の個別のクライアントから生成または消費されるデータを分割するために使用され、ユーザープロファイル、カタログアイテムなどを保存するのに役立ちます。
.NETSDKが提供するRangePartitionResolverを使用した範囲分割の簡単な例を見てみましょう。
Step 1−新しいDocumentClientを作成し、CreateCollectionsタスクで2つのコレクションを作成します。1つにはAからMで始まるユーザーIDを持つユーザーのドキュメントが含まれ、もう1つにはユーザーIDNからZのドキュメントが含まれます。
private static async Task CreateCollections(DocumentClient client) {
await client.CreateDocumentCollectionAsync(“dbs/myfirstdb”, new DocumentCollection {
Id = “CollectionAM” });
await client.CreateDocumentCollectionAsync(“dbs/myfirstdb”, new DocumentCollection {
Id = “CollectionNZ” });
}
Step 2 −データベースの範囲リゾルバを登録します。
Step 3−パーティションキーのデータ型である新しいRangePartitionResolver <string>を作成します。コンストラクターは、パーティションキーのプロパティ名と、シャードマップまたはパーティションマップであるディクショナリの2つのパラメーターを取ります。これは、リゾルバー用に事前定義している範囲と対応するコレクションのリストです。
private static void RegisterRangeResolver(DocumentClient client) {
//Note: \uffff is the largest UTF8 value, so M\ufff includes all strings that start with M.
var resolver = new RangePartitionResolver<string>(
"userId", new Dictionary<Range<string>, string>() {
{ new Range<string>("A", "M\uffff"), "dbs/myfirstdb/colls/CollectionAM" },
{ new Range<string>("N", "Z\uffff"), "dbs/myfirstdb/colls/CollectionNZ" },
});
client.PartitionResolvers["dbs/myfirstdb"] = resolver;
}
ここでは、可能な限り最大のUTF-8値をエンコードする必要があります。そうでなければ、最初の範囲は、単一のMを除くどのMでも一致せず、同様に2番目の範囲のZでも一致しません。したがって、ここでは、このエンコードされた値を、パーティションキーで照合するためのワイルドカードと考えることができます。
Step 4−リゾルバーを作成したら、現在のDocumentClientを使用してデータベースに登録します。これを行うには、PartitionResolverのディクショナリプロパティに割り当てるだけです。
通常のようにコレクションではなく、データベースに対してドキュメントを作成してクエリを実行します。リゾルバーはこのマップを使用して、リクエストを適切なコレクションにルーティングします。
それでは、いくつかのドキュメントを作成しましょう。最初にuserIdKirk用に1つ作成し、次にSpock用に1つ作成します。
private static async Task CreateDocumentsAcrossPartitions(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("**** Create Documents Across Partitions ****");
var kirkDocument = await client.CreateDocumentAsync("dbs/myfirstdb", new { userId =
"Kirk", title = "Captain" });
Console.WriteLine("Document 1: {0}", kirkDocument.Resource.SelfLink);
var spockDocument = await client.CreateDocumentAsync("dbs/myfirstdb", new { userId =
"Spock", title = "Science Officer" });
Console.WriteLine("Document 2: {0}", spockDocument.Resource.SelfLink);
}
ここでの最初のパラメーターは、特定のコレクションではなく、データベースへの自己リンクです。これはパーティションリゾルバーなしでは不可能ですが、パーティションリゾルバーを使用するとシームレスに機能します。
両方のドキュメントはデータベースmyfirstdbに保存されましたが、RangePartitionResolverが正しく機能している場合、KirkはAからMのコレクションに保存され、SpockはNからZのコレクションに保存されていることがわかります。
次のコードに示すように、CreateDocumentClientタスクからこれらを呼び出しましょう。
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
await CreateCollections(client);
RegisterRangeResolver(client);
await CreateDocumentsAcrossPartitions(client);
}
}
上記のコードを実行すると、次の出力が表示されます。
**** Create Documents Across Partitions ****
Document 1: dbs/Ic8LAA==/colls/Ic8LAO2DxAA=/docs/Ic8LAO2DxAABAAAAAAAAAA==/
Document 2: dbs/Ic8LAA==/colls/Ic8LAP12QAE=/docs/Ic8LAP12QAEBAAAAAAAAAA==/
ご覧のとおり、2つのドキュメントの自己リンクは、2つの別々のコレクションに存在するため、異なるリソースIDを持っています。
DocumentDBデータ移行ツールを使用すると、データをDocumentDBに簡単に移行できます。DocumentDB Data Migration Toolは、Microsoftダウンロードセンターからダウンロードできる無料のオープンソースユーティリティです。https://www.microsoft.com/
移行ツールは多くのデータソースをサポートしており、そのうちのいくつかを以下に示します-
- SQLサーバー
- JSONファイル
- カンマ区切り値(CSV)のフラットファイル
- MongoDB
- Azureテーブルストレージ
- Amazon DynamoDB
- HBase、さらには他のDocumentDBデータベース
DocumentDBデータ移行ツールをダウンロードした後、zipファイルを抽出します。
次のスクリーンショットに示すように、このフォルダーに2つの実行可能ファイルが表示されます。
まず、コマンドラインインターフェイスを備えたコンソールバージョンであるdt.exeがあり、次にグラフィカルユーザーインターフェイスを備えたデスクトップバージョンであるdtui.exeがあります。
GUIバージョンを起動しましょう。
ウェルカムページが表示されます。[ソース情報]ページの[次へ]をクリックします。
ここでデータソースを構成し、ドロップダウンメニューからサポートされている多くの選択肢を確認できます。
選択すると、それに応じて[ソース情報]ページの残りの部分が変わります。
DocumentDBデータ移行ツールを使用してDocumentDBにデータをインポートするのは非常に簡単です。上記の例を実行し、他のデータファイルも使用することをお勧めします。
DocumentDBは、DocumentDBリソースへのアクセスを制御するための概念を提供します。DocumentDBリソースへのアクセスは、マスターキートークンまたはリソーストークンによって管理されます。リソーストークンに基づく接続は、トークンで指定されたリソースにのみアクセスでき、他のリソースにはアクセスできません。リソーストークンは、ユーザーのアクセス許可に基づいています。
最初に1人以上のユーザーを作成し、これらはデータベースレベルで定義されます。
次に、各ユーザーにアクセスを許可するリソースに基づいて、ユーザーごとに1つ以上のアクセス許可を作成します。
各権限は、特定のリソースへの読み取り専用またはフルアクセスのいずれかを許可し、データベース内の任意のユーザーリソースにすることができるリソーストークンを生成します。
ユーザーはデータベースレベルで定義され、権限はユーザーごとに定義されます。
ユーザーと権限は、データベース内のすべてのコレクションに適用されます。
DocumentDBできめ細かいセキュリティを実現するために、ユーザーとアクセス許可を定義する方法を学習する簡単な例を見てみましょう。
新しいDocumentClientから始めて、myfirstdbデータベースをクエリします。
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
'myfirstdb'").AsEnumerable().First();
collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
"SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();
var alice = await CreateUser(client, "Alice");
var tom = await CreateUser(client, "Tom");
}
}
以下は、CreateUserの実装です。
private async static Task<User> CreateUser(DocumentClient client, string userId) {
Console.WriteLine();
Console.WriteLine("**** Create User {0} in {1} ****", userId, database.Id);
var userDefinition = new User { Id = userId };
var result = await client.CreateUserAsync(database.SelfLink, userDefinition);
var user = result.Resource;
Console.WriteLine("Created new user");
ViewUser(user);
return user;
}
Step 1−作成するリソースと同様に、AliceとTomの2人のユーザーを作成し、目的のIDを使用して定義オブジェクトを作成し、createメソッドを呼び出します。この場合、データベースのSelfLinkとuserDefinitionを使用してCreateUserAsyncを呼び出します。新しく作成されたユーザーオブジェクトを取得したリソースプロパティから結果を取得します。
次に、これら2人の新しいユーザーをデータベースに表示します。
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−データベースのUsersLinkに対してCreateUserQueryを呼び出して、すべてのユーザーのリストを取得します。次に、それらをループして、それらのプロパティを表示します。
次に、最初にそれらを作成する必要があります。したがって、MyCollectionコレクションへの読み取り/書き込みアクセス許可をAliceに許可したいのに、Tomはコレクション内のドキュメントしか読み取れないとしましょう。
await CreatePermission(client, alice, "Alice Collection Access", PermissionMode.All,
collection);
await CreatePermission(client, tom, "Tom Collection Access", PermissionMode.Read,
collection);
Step 3− MyCollectionコレクションであるリソースに対するアクセス許可を作成して、そのリソースをSelfLinkにする必要があります。
Step 4 −次に、アリスの場合はこのコレクションにPermission.Allを作成し、トムの場合はこのコレクションにPermission.Readを作成します。
以下は、CreatePermissionの実装です。
private async static Task CreatePermission(DocumentClient client, User user,
string permId, PermissionMode permissionMode, string resourceLink) {
Console.WriteLine();
Console.WriteLine("**** Create Permission {0} for {1} ****", permId, user.Id);
var permDefinition = new Permission {
Id = permId,
PermissionMode = permissionMode,
ResourceLink = resourceLink
};
var result = await client.CreatePermissionAsync(user.SelfLink, permDefinition);
var perm = result.Resource;
Console.WriteLine("Created new permission");
ViewPermission(perm);
}
これまでに予想されるように、これを行うには、新しいパーミッションの定義オブジェクトを作成します。これには、IdとpermissionMode(Permission.AllまたはPermission.Readのいずれか)、および保護されているリソースのSelfLinkが含まれます。許可を得て。
Step 5 − CreatePermissionAsyncを呼び出し、結果のリソースプロパティから作成された権限を取得します。
作成された権限を表示するための、ViewPermissionsの実装は次のとおりです。
private static void ViewPermissions(DocumentClient client, User user) {
Console.WriteLine();
Console.WriteLine("**** View Permissions for {0} ****", user.Id);
var perms = client.CreatePermissionQuery(user.PermissionsLink).ToList();
var i = 0;
foreach (var perm in perms) {
i++;
Console.WriteLine();
Console.WriteLine("Permission #{0}", i);
ViewPermission(perm);
}
Console.WriteLine();
Console.WriteLine("Total permissions for {0}: {1}", user.Id, perms.Count);
}
private static void ViewPermission(Permission perm) {
Console.WriteLine("Permission ID: {0} ", perm.Id);
Console.WriteLine("Resource ID: {0} ", perm.ResourceId);
Console.WriteLine("Permission Mode: {0} ", perm.PermissionMode);
Console.WriteLine("Token: {0} ", perm.Token);
Console.WriteLine("Timestamp: {0} ", perm.Timestamp);
}
今回は、ユーザーのアクセス許可リンクに対するアクセス許可クエリであり、ユーザーに返された各アクセス許可を一覧表示するだけです。
アリスとトムの権限を削除しましょう。
await DeletePermission(client, alice, "Alice Collection Access");
await DeletePermission(client, tom, "Tom Collection Access");
以下は、DeletePermissionの実装です。
private async static Task DeletePermission(DocumentClient client, User user,
string permId) {
Console.WriteLine();
Console.WriteLine("**** Delete Permission {0} from {1} ****", permId, user.Id);
var query = new SqlQuerySpec {
QueryText = "SELECT * FROM c WHERE c.id = @id",
Parameters = new SqlParameterCollection {
new SqlParameter { Name = "@id", Value = permId }
}
};
Permission perm = client.CreatePermissionQuery(user.PermissionsLink, query)
.AsEnumerable().First();
await client.DeletePermissionAsync(perm.SelfLink);
Console.WriteLine("Deleted permission {0} from user {1}", permId, user.Id);
}
Step 6 −権限を削除するには、権限IDでクエリを実行してSelfLinkを取得してから、SelfLinkを使用して権限を削除します。
次に、ユーザー自身を削除しましょう。両方のユーザーを削除しましょう。
await DeleteUser(client, "Alice");
await DeleteUser(client, "Tom");
以下は、DeleteUserの実装です。
private async static Task DeleteUser(DocumentClient client, string userId) {
Console.WriteLine();
Console.WriteLine("**** Delete User {0} in {1} ****", userId, database.Id);
var query = new SqlQuerySpec {
QueryText = "SELECT * FROM c WHERE c.id = @id",
Parameters = new SqlParameterCollection {
new SqlParameter { Name = "@id", Value = userId }
}
};
User user = client.CreateUserQuery(database.SelfLink, query).AsEnumerable().First();
await client.DeleteUserAsync(user.SelfLink);
Console.WriteLine("Deleted user {0} from database {1}", userId, database.Id);
}
Step 7 −最初にクエリを実行してSelfLinkを取得し、次にDeleteUserAsyncを呼び出してユーザーオブジェクトを削除します。
以下は、上記のすべてのタスクを呼び出すCreateDocumentClientタスクの実装です。
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
'myfirstdb'").AsEnumerable().First();
collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
"SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();
ViewUsers(client);
var alice = await CreateUser(client, "Alice");
var tom = await CreateUser(client, "Tom");
ViewUsers(client);
ViewPermissions(client, alice);
ViewPermissions(client, tom);
string collectionLink = client.CreateDocumentCollectionQuery(database.SelfLink,
"SELECT VALUE c._self FROM c WHERE c.id = 'MyCollection'")
.AsEnumerable().First().Value;
await CreatePermission(client, alice, "Alice Collection Access", PermissionMode.All,
collectionLink);
await CreatePermission(client, tom, "Tom Collection Access", PermissionMode.Read,
collectionLink);
ViewPermissions(client, alice);
ViewPermissions(client, tom);
await DeletePermission(client, alice, "Alice Collection Access");
await DeletePermission(client, tom, "Tom Collection Access");
await DeleteUser(client, "Alice");
await DeleteUser(client, "Tom");
}
}
上記のコードをコンパイルして実行すると、次の出力が表示されます。
**** View Users in myfirstdb ****
Total users in database myfirstdb: 0
**** Create User Alice in myfirstdb ****
Created new user
User ID: Alice
Resource ID: kV5oAC56NwA=
Self Link: dbs/kV5oAA==/users/kV5oAC56NwA=/
Permissions Link: dbs/kV5oAA==/users/kV5oAC56NwA=/permissions/
Timestamp: 12/17/2015 5:44:19 PM
**** Create User Tom in myfirstdb ****
Created new user
User ID: Tom
Resource ID: kV5oAALxKgA=
Self Link: dbs/kV5oAA==/users/kV5oAALxKgA=/
Permissions Link: dbs/kV5oAA==/users/kV5oAALxKgA=/permissions/
Timestamp: 12/17/2015 5:44:21 PM
**** View Users in myfirstdb ****
User #1
User ID: Tom
Resource ID: kV5oAALxKgA=
Self Link: dbs/kV5oAA==/users/kV5oAALxKgA=/
Permissions Link: dbs/kV5oAA==/users/kV5oAALxKgA=/permissions/
Timestamp: 12/17/2015 5:44:21 PM
User #2
User ID: Alice
Resource ID: kV5oAC56NwA=
Self Link: dbs/kV5oAA==/users/kV5oAC56NwA=/
Permissions Link: dbs/kV5oAA==/users/kV5oAC56NwA=/permissions/
Timestamp: 12/17/2015 5:44:19 PM
Total users in database myfirstdb: 2
**** View Permissions for Alice ****
Total permissions for Alice: 0
**** View Permissions for Tom ****
Total permissions for Tom: 0
**** Create Permission Alice Collection Access for Alice ****
Created new permission
Permission ID: Alice Collection Access
Resource ID: kV5oAC56NwDON1RduEoCAA==
Permission Mode: All
Token: type=resource&ver=1&sig=zB6hfvvleC0oGGbq5cc67w==;Zt3Lx
Ol14h8pd6/tyF1h62zbZKk9VwEIATIldw4ZyipQGW951kirueAKdeb3MxzQ7eCvDfvp7Y/ZxFpnip/D G
JYcPyim5cf+dgLvos6fUuiKSFSul7uEKqp5JmJqUCyAvD7w+qt1Qr1PmrJDyAIgbZDBFWGe2VT9FaBH o
PYwrLjRlnH0AxfbrR+T/UpWMSSHtLB8JvNFZNSH8hRjmQupuTSxCTYEC89bZ/pS6fNmNg8=;
Timestamp: 12/17/2015 5:44:28 PM
**** Create Permission Tom Collection Access for Tom ****
Created new permission
Permission ID: Tom Collection Access
Resource ID: kV5oAALxKgCMai3JKWdfAA==
Permission Mode: Read
Token: type=resource&ver=1&sig=ieBHKeyi6EY9ZOovDpe76w==;92gwq
V4AxKaCJ2dLS02VnJiig/5AEbPcfo1xvOjR10uK3a3FUMFULgsaK8nzxdz6hLVCIKUj6hvMOTOSN8Lt 7
i30mVqzpzCfe7JO3TYSJEI9D0/5HbMIEgaNJiCu0JPPwsjVecTytiLN56FHPguoQZ7WmUAhVTA0IMP6 p
jQpLDgJ43ZaG4Zv3qWJiO689balD+egwiU2b7RICH4j6R66UVye+GPxq/gjzqbHwx79t54=;
Timestamp: 12/17/2015 5:44:30 PM
**** View Permissions for Alice ****
Permission #1
Permission ID: Alice Collection Access
Resource ID: kV5oAC56NwDON1RduEoCAA==
Permission Mode: All
Token: type=resource&ver=1&sig=BSzz/VNe9j4IPJ9M31Mf4Q==;Tcq/B
X50njB1vmANZ/4aHj/3xNkghaqh1OfV95JMi6j4v7fkU+gyWe3mJasO3MJcoop9ixmVnB+RKOhFaSxE l
P37SaGuIIik7GAWS+dcEBWglMefc95L2YkeNuZsjmmW5b+a8ELCUg7N45MKbpzkp5BrmmGVJ7h4Z4pf D
rdmehYLuxSPLkr9ndbOOrD8E3bux6TgXCsgYQscpIlJHSKCKHUHfXWBP2Y1LV2zpJmRjis=;
Timestamp: 12/17/2015 5:44:28 PM
Total permissions for Alice: 1
**** View Permissions for Tom ****
Permission #1
Permission ID: Tom Collection Access
Resource ID: kV5oAALxKgCMai3JKWdfAA==
Permission Mode: Read
Token: type=resource&ver=1&sig=NPkWNJp1mAkCASE8KdR6PA==;ur/G2
V+fDamBmzECux000VnF5i28f8WRbPwEPxD1DMpFPqYcu45wlDyzT5A5gBr3/R3qqYkEVn8bU+een6Gl j
L6vXzIwsZfL12u/1hW4mJT2as2PWH3eadry6Q/zRXHAxV8m+YuxSzlZPjBFyJ4Oi30mrTXbBAEafZhA 5
yvbHkpLmQkLCERy40FbIFOzG87ypljREpwWTKC/z8RSrsjITjAlfD/hVDoOyNJwX3HRaz4=;
Timestamp: 12/17/2015 5:44:30 PM
Total permissions for Tom: 1
**** Delete Permission Alice Collection Access from Alice ****
Deleted permission Alice Collection Access from user Alice
**** Delete Permission Tom Collection Access from Tom ****
Deleted permission Tom Collection Access from user Tom
**** Delete User Alice in myfirstdb ****
Deleted user Alice from database myfirstdb
**** Delete User Tom in myfirstdb ****
Deleted user Tom from database myfirstdb
この章では、DocumentDBに保存されているデータを視覚化する方法を学習します。マイクロソフトは、データをリッチなビジュアルに変換するPower BIDesktopツールを提供しました。また、さまざまなデータソースからデータを取得し、データをマージして変換し、強力なレポートと視覚化を作成し、レポートをPowerBIに公開することもできます。
Power BI Desktopの最新バージョンでは、MicrosoftはDocumentDBのサポートも追加しており、DocumentDBアカウントに接続できるようになりました。このツールはリンクからダウンロードできます。https://powerbi.microsoft.com
前の章でインポートした地震データを視覚化する例を見てみましょう。
Step 1 −ツールがダウンロードされたら、PowerBIデスクトップを起動します。
Step 2 − [外部データ]グループの[ホーム]タブにある[データの取得]オプションをクリックすると、[データの取得]ページが表示されます。
Step 3 − Microsoft Azure DocumentDB(ベータ)オプションを選択し、[接続]ボタンをクリックします。
Step 4 −データを視覚化するAzure DocumentDBアカウント、データベース、およびコレクションのURLを入力し、[OK]を押します。
このエンドポイントに初めて接続する場合は、アカウントキーの入力を求められます。
Step 5 − Azureポータルで使用可能な各DocumentDBアカウントに固有のアカウントキー(主キー)を入力し、[接続]をクリックします。
アカウントが正常に接続されると、指定されたデータベースからデータが取得されます。プレビューペインにはレコードアイテムのリストが表示され、ドキュメントはPowerBIではレコードタイプとして表されます。
Step 6 −「編集」ボタンをクリックしてクエリエディタを起動します。
Step 7 − Power BIクエリエディターで、中央のペインに[ドキュメント]列が表示されます。[ドキュメント]列ヘッダーの右側にあるエキスパンダーをクリックして、表示する列を選択します。
ご覧のとおり、緯度と経度は別々の列になっていますが、データは緯度と経度の座標形式で視覚化されています。
Step 8 −これを行うには、[列の追加]タブをクリックします。
Step 9 −次のページを表示する[カスタム列の追加]を選択します。
Step 10−新しい列名を指定します。たとえば、LatLongと、緯度と経度を1つの列にコンマで区切って組み合わせる式を指定します。以下は式です。
Text.From([latitude])&", "&Text.From([longitude])
Step 11 − [OK]をクリックして続行すると、新しい列が追加されたことがわかります。
Step 12 − [ホーム]タブに移動し、[閉じて適用]オプションをクリックします。
Step 13−フィールドをレポートキャンバスにドラッグアンドドロップして、レポートを作成できます。右側に、2つのペインがあります。1つは[視覚化]ペインで、もう1つは[フィールド]ペインです。
各地震の場所を示すマップビューを作成しましょう。
Step 14 −マップのビジュアルタイプを[ビジュアライゼーション]ペインからドラッグします。
Step 15−ここで、LatLongフィールドを[フィールド]ペインから[ビジュアライゼーション]ペインの[場所]プロパティにドラッグアンドドロップします。次に、マグニチュードフィールドをValuesプロパティにドラッグアンドドロップします。
Step 16 −被写界深度フィールドを彩度プロパティにドラッグアンドドロップします。
これで、各地震の場所を示す一連のバブルを示すマップビジュアルが表示されます。