Documentdb-sql-quick-guide
DocumentDB SQL-概要
DocumentDBは、Azure上で実行されるMicrosoftの最新のNoSQLドキュメントデータベースプラットフォームです。 このチュートリアルでは、DocumentDBでサポートされている特別なバージョンのSQLを使用したドキュメントのクエリについてすべて学習します。
NoSQLドキュメントデータベース
DocumentDBはMicrosoftの最新のNoSQLドキュメントデータベースですが、NoSQLドキュメントデータベースと言うとき、NoSQLとドキュメントデータベースとは正確には何を意味しますか?
- SQLは、リレーショナルデータベースの従来のクエリ言語である構造化クエリ言語を意味します。 SQLは、多くの場合、リレーショナルデータベースと同一視されます。
- NoSQLデータベースを非リレーショナルデータベースと考えると、非常に便利です。したがって、NoSQLは本当に非リレーショナルを意味します。
次のようなキー値ストアを含むさまざまな種類のNoSQLデータベースがあります-
- Azureテーブルストレージ
- Cassandraなどの列ベースのストア
- NEO4のようなグラフデータベース
- MongoDBやAzure DocumentDBなどのドキュメントデータベース
なぜSQL構文なのか?
これは最初は奇妙に聞こえるかもしれませんが、NoSQLデータベースであるDocumentDBでは、SQLを使用してクエリを実行します。 前述のように、これはJSONおよびJavaScriptセマンティクスに根ざしたSQLの特別なバージョンです。
- SQLは単なる言語ですが、リッチで表現力のある非常に人気のある言語でもあります。 したがって、データベースからドキュメントを取得する場合に学習する必要があるクエリを表現するまったく新しい方法を考え出すよりも、SQLの方言を使用することは間違いなく良い考えのようです。
- SQLはリレーショナルデータベース用に設計されており、DocumentDBは非リレーショナルドキュメントデータベースです。 DocumentDBチームは、ドキュメントデータベースの非リレーショナルの世界にSQL構文を実際に適用しました。これは、JSONおよびJavaScriptでSQLをルート化することを意味します。
- この言語は今でもおなじみのSQLとして読みますが、セマンティクスはすべてリレーショナルテーブルではなく、スキーマフリーのJSONドキュメントに基づいています。 DocumentDBでは、SQLデータ型ではなくJavaScriptデータ型を使用します。 SELECT、FROM、WHEREなどに精通していますが、数値と文字列に限定されているJavaScript型、オブジェクト、配列、ブール値、nullは、広範囲のSQLデータ型よりもはるかに少ないです。
- 同様に、式はT-SQLの何らかの形式ではなくJavaScript式として評価されます。 たとえば、非正規化データの世界では、行と列ではなく、ネストされた配列とオブジェクトを含む階層構造を持つスキーマフリーのドキュメントを扱います。
SQLはどのように機能しますか?
DocumentDBチームは、いくつかの革新的な方法でこの質問に答えました。 それらのいくつかは次のようにリストされています-
- まず、ドキュメント内のすべてのプロパティに自動的にインデックスを付けるデフォルトの動作を変更していないと仮定すると、クエリ内でドット表記を使用して、ドキュメント内のネストの深さに関係なく、任意のプロパティへのパスをナビゲートできます。
- また、リレーショナル世界の2つのテーブル間で結合が実行される方法と非常によく似た方法で、ネストされた配列要素がドキュメント内の親要素と結合されるドキュメント内結合を実行できます。
- クエリは、データベースからドキュメントをそのまま返すことができます。または、必要なドキュメントデータの量に応じて、必要なカスタムJSON形状を投影できます。
- DocumentDBのSQLは、次のような一般的な演算子の多くをサポートしています-
- 算術演算とビット演算
- ANDおよびORロジック
- 同等性と範囲の比較
- 文字列の連結
- クエリ言語は、組み込み関数のホストもサポートしています。
DocumentDB SQL-選択句
Azureポータルには、DocumentDBデータベースに対してSQLクエリを実行できるクエリエクスプローラーがあります。 クエリエクスプローラーを使用して、可能な限り単純なクエリから始めて、クエリ言語のさまざまな機能を紹介します。
- ステップ1 *-Azureポータルを開き、データベースブレードで[クエリエクスプローラー]ブレードをクリックします。
クエリはコレクションのスコープ内で実行されるため、クエリエクスプローラーではこのドロップダウンでコレクションを選択できます。 3つのドキュメントを含むファミリコレクションに設定したままにします。 この例では、これら3つのドキュメントを考えてみましょう。
以下は AndersenFamily ドキュメントです。
{
"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
}
以下は SmithFamily ドキュメントです。
{
"id": "SmithFamily",
"parents": [
{ "familyName": "Smith", "givenName": "James" },
{ "familyName": "Curtis", "givenName": "Helen" }
],
"children": [
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"givenName": "John",
"gender": "male",
"grade": 7,
"pets": [
{ "givenName": "Tweetie", "type": "Bird" }
]
}
],
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
"isRegistered": true
}
以下は WakefieldFamily ドキュメントです。
{
"id": "WakefieldFamily",
"parents": [
{ "familyName": "Wakefield", "givenName": "Robin" },
{ "familyName": "Miller", "givenName": "Ben" }
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{ "givenName": "Charlie Brown", "type": "Dog" },
{ "givenName": "Tiger", "type": "Cat" },
{ "givenName": "Princess", "type": "Cat" }
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{ "givenName": "Jake", "type": "Snake" }
]
}
],
"location": { "state": "NY", "county": "Manhattan", "city": "NY" },
"isRegistered": false
}
クエリエクスプローラーは、コレクションからすべてのドキュメントを取得するだけの簡単なクエリSELECT * FROM cで開きます。 単純ですが、リレーショナルデータベースの同等のクエリとはまったく異なります。
- ステップ2 *-リレーショナルデータベースでは、SELECT *はDocumentDB内にある間にすべての列を返すことを意味します。 つまり、結果に含まれる各ドキュメントをデータベースに保存されているとおりに正確に返す必要があるということです。
しかし、単にSELECT *を発行するのではなく、特定のプロパティと式を選択すると、結果の各ドキュメントに必要な新しい形状が投影されます。
- ステップ3 *-[実行]をクリックしてクエリを実行し、[結果]ブレードを開きます。
ご覧のとおり、WakefieldFamily、SmithFamily、およびAndersonFamilyが取得されます。
以下は、 SELECT FROM c *クエリの結果として取得される3つのドキュメントです。
[
{
"id": "WakefieldFamily",
"parents": [
{
"familyName": "Wakefield",
"givenName": "Robin"
},
{
"familyName": "Miller",
"givenName": "Ben"
}
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{
"givenName": "Charlie Brown",
"type": "Dog"
},
{
"givenName": "Tiger",
"type": "Cat"
},
{
"givenName": "Princess",
"type": "Cat"
}
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{
"givenName": "Jake",
"type": "Snake"
}
]
}
],
"location": {
"state": "NY",
"county": "Manhattan",
"city": "NY"
},
"isRegistered": false,
"_rid": "Ic8LAJFujgECAAAAAAAAAA==",
"_ts": 1450541623,
"_self": "dbs/Ic8LAA==/colls/Ic8LAJFujgE=/docs/Ic8LAJFujgECAAAAAAAAAA==/",
"_etag": "\"00000500-0000-0000-0000-567582370000\"",
"_attachments": "attachments/"
},
{
"id": "SmithFamily",
"parents": [
{
"familyName": "Smith",
"givenName": "James"
},
{
"familyName": "Curtis",
"givenName": "Helen"
}
],
"children": [
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"givenName": "John",
"gender": "male",
"grade": 7,
"pets": [
{
"givenName": "Tweetie",
"type": "Bird"
}
]
}
],
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
"isRegistered": true,
"_rid": "Ic8LAJFujgEDAAAAAAAAAA==",
"_ts": 1450541623,
"_self": "dbs/Ic8LAA==/colls/Ic8LAJFujgE=/docs/Ic8LAJFujgEDAAAAAAAAAA==/",
"_etag": "\"00000600-0000-0000-0000-567582370000\"",
"_attachments": "attachments/"
},
{
"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,
"_rid": "Ic8LAJFujgEEAAAAAAAAAA==",
"_ts": 1450541624,
"_self": "dbs/Ic8LAA==/colls/Ic8LAJFujgE=/docs/Ic8LAJFujgEEAAAAAAAAAA==/",
"_etag": "\"00000700-0000-0000-0000-567582380000\"",
"_attachments": "attachments/"
}
]
ただし、これらの結果には、すべてアンダースコア文字が前に付いたシステム生成のプロパティも含まれます。
DocumentDB SQL-句から
この章では、FROM句について説明します。FROM句は、通常のSQLの標準のFROM句とはまったく異なります。
クエリは常に特定のコレクションのコンテキスト内で実行され、コレクション内のドキュメント間で結合できないため、FROM句が必要な理由がわかりません。 実際には含まれていませんが、含まれていない場合、コレクション内のドキュメントをクエリすることはありません。
この句の目的は、クエリが動作するデータソースを指定することです。 通常、コレクション全体がソースですが、代わりにコレクションのサブセットを指定できます。 FROM <from_specification>句は、ソースがクエリの後半でフィルターまたは投影されない限りオプションです。
もう一度同じ例を見てみましょう。 以下は AndersenFamily ドキュメントです。
{
"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
}
以下は SmithFamily ドキュメントです。
{
"id": "SmithFamily",
"parents": [
{ "familyName": "Smith", "givenName": "James" },
{ "familyName": "Curtis", "givenName": "Helen" }
],
"children": [
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"givenName": "John",
"gender": "male",
"grade": 7,
"pets": [
{ "givenName": "Tweetie", "type": "Bird" }
]
}
],
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
"isRegistered": true
}
以下は WakefieldFamily ドキュメントです。
{
"id": "WakefieldFamily",
"parents": [
{ "familyName": "Wakefield", "givenName": "Robin" },
{ "familyName": "Miller", "givenName": "Ben" }
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{ "givenName": "Charlie Brown", "type": "Dog" },
{ "givenName": "Tiger", "type": "Cat" },
{ "givenName": "Princess", "type": "Cat" }
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{ "givenName": "Jake", "type": "Snake" }
]
}
],
"location": { "state": "NY", "county": "Manhattan", "city": "NY" },
"isRegistered": false
}
上記のクエリで、「 SELECT FROM c *」は、Familiesコレクション全体が列挙のソースであることを示しています。
サブドキュメント
また、ソースをより小さなサブセットに減らすこともできます。 各ドキュメントのサブツリーのみを取得する場合、次の例に示すように、サブルートがソースになる可能性があります。
私たちは次のクエリを実行するとき-
SELECT * FROM Families.parents
次のサブドキュメントが取得されます。
[
[
{
"familyName": "Wakefield",
"givenName": "Robin"
},
{
"familyName": "Miller",
"givenName": "Ben"
}
],
[
{
"familyName": "Smith",
"givenName": "James"
},
{
"familyName": "Curtis",
"givenName": "Helen"
}
],
[
{
"firstName": "Thomas",
"relationship": "father"
},
{
"firstName": "Mary Kay",
"relationship": "mother"
}
]
]
このクエリの結果、親サブドキュメントのみが取得されることがわかります。
DocumentDB SQL-Where句
この章では、WHERE句について説明します。これは、FROM句と同様にオプションです。 ソースによって提供されるJSONドキュメントの形式でデータを取得する際に条件を指定するために使用されます。 JSONドキュメントは、結果に対して考慮されるために、指定された条件が「true」であると評価する必要があります。 指定された条件が満たされた場合のみ、JSONドキュメントの形式で特定のデータを返します。 WHERE句を使用してレコードをフィルタリングし、必要なレコードのみを取得できます。
この例では、同じ3つのドキュメントを検討します。 以下は AndersenFamily ドキュメントです。
{
"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
}
以下は SmithFamily ドキュメントです。
{
"id": "SmithFamily",
"parents": [
{ "familyName": "Smith", "givenName": "James" },
{ "familyName": "Curtis", "givenName": "Helen" }
],
"children": [
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"givenName": "John",
"gender": "male",
"grade": 7,
"pets": [
{ "givenName": "Tweetie", "type": "Bird" }
]
}
],
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
"isRegistered": true
}
以下は WakefieldFamily ドキュメントです。
{
"id": "WakefieldFamily",
"parents": [
{ "familyName": "Wakefield", "givenName": "Robin" },
{ "familyName": "Miller", "givenName": "Ben" }
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{ "givenName": "Charlie Brown", "type": "Dog" },
{ "givenName": "Tiger", "type": "Cat" },
{ "givenName": "Princess", "type": "Cat" }
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{ "givenName": "Jake", "type": "Snake" }
]
}
],
"location": { "state": "NY", "county": "Manhattan", "city": "NY" },
"isRegistered": false
}
WHERE句が使用されている簡単な例を見てみましょう。
このクエリでは、WHERE句に(WHERE f.id = "WakefieldFamily")条件が指定されています。
SELECT *
FROM f
WHERE f.id = "WakefieldFamily"
上記のクエリを実行すると、次の出力に示すように、WakefieldFamilyの完全なJSONドキュメントが返されます。
[
{
"id": "WakefieldFamily",
"parents": [
{
"familyName": "Wakefield",
"givenName": "Robin"
},
{
"familyName": "Miller",
"givenName": "Ben"
}
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{
"givenName": "Charlie Brown",
"type": "Dog"
},
{
"givenName": "Tiger",
"type": "Cat"
},
{
"givenName": "Princess",
"type": "Cat"
}
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{
"givenName": "Jake",
"type": "Snake"
}
]
}
],
"location": {
"state": "NY",
"county": "Manhattan",
"city": "NY"
},
"isRegistered": false,
"_rid": "Ic8LAJFujgECAAAAAAAAAA==",
"_ts": 1450541623,
"_self": "dbs/Ic8LAA==/colls/Ic8LAJFujgE=/docs/Ic8LAJFujgECAAAAAAAAAA==/",
"_etag": "\"00000500-0000-0000-0000-567582370000\"",
"_attachments": "attachments/"
}
]
DocumentDB SQL-演算子
演算子は、比較や算術演算などの操作を実行するために主にSQL WHERE句で使用される予約語または文字です。 DocumentDB SQLは、さまざまなスカラー式もサポートしています。 最も一般的に使用されるのは、*バイナリ式と単項式*です。
現在、次のSQL演算子がサポートされており、クエリで使用できます。
SQL比較演算子
以下は、DocumentDB SQL文法で使用可能なすべての比較演算子のリストです。
S.No. | Operators & Description |
---|---|
1 |
= 2つのオペランドの値が等しいかどうかを確認します。 はいの場合、条件は真になります。 |
2 |
!= 2つのオペランドの値が等しいかどうかを確認します。 値が等しくない場合、条件は真になります。 |
3 |
<> 2つのオペランドの値が等しいかどうかを確認します。 値が等しくない場合、条件は真になります。 |
4 |
> 左オペランドの値が右オペランドの値より大きいかどうかを確認します。 はいの場合、条件は真になります。 |
5 |
< 左オペランドの値が右オペランドの値より小さいかどうかを確認します。 はいの場合、条件は真になります。 |
6 |
>= 左オペランドの値が右オペランドの値以上かどうかを確認します。 はいの場合、条件は真になります。 |
7 |
⇐ 左オペランドの値が右オペランドの値以下かどうかを確認します。 はいの場合、条件は真になります。 |
SQL論理演算子
以下は、DocumentDB SQL文法で使用可能なすべての論理演算子のリストです。
S.No. | Operators & Description |
---|---|
1 |
AND AND演算子を使用すると、SQLステートメントのWHERE句に複数の条件を含めることができます。 |
2 |
BETWEEN BETWEEN演算子は、最小値と最大値を指定して、値のセット内にある値を検索するために使用されます。 |
3 |
IN IN演算子は、値を指定されたリテラル値のリストと比較するために使用されます。 |
4 |
OR OR演算子は、SQLステートメントのWHERE句で複数の条件を結合するために使用されます。 |
5 |
NOT NOT演算子は、使用される論理演算子の意味を逆にします。 たとえば、NOT EXISTS、NOT BETWEEN、NOT INなど。 これは否定演算子です。 |
SQL算術演算子
以下は、DocumentDB SQL文法で使用可能なすべての算術演算子のリストです。
S.No. | Operators & Description |
---|---|
1 |
+ 追加-演算子の両側に値を追加します。 |
2 |
- 減算-右側のオペランドを左側のオペランドから減算します。 |
3 | 乗算-演算子の両側の値を乗算します。 |
4 |
/
|
5 |
% モジュラス-左側のオペランドを右側のオペランドで除算し、剰余を返します。 |
この例でも同じドキュメントを検討します。 以下は AndersenFamily ドキュメントです。
{
"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
}
以下は SmithFamily ドキュメントです。
{
"id": "SmithFamily",
"parents": [
{ "familyName": "Smith", "givenName": "James" },
{ "familyName": "Curtis", "givenName": "Helen" }
],
"children": [
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"givenName": "John",
"gender": "male",
"grade": 7,
"pets": [
{ "givenName": "Tweetie", "type": "Bird" }
]
}
],
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
"isRegistered": true
}
以下は WakefieldFamily ドキュメントです。
{
"id": "WakefieldFamily",
"parents": [
{ "familyName": "Wakefield", "givenName": "Robin" },
{ "familyName": "Miller", "givenName": "Ben" }
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{ "givenName": "Charlie Brown", "type": "Dog" },
{ "givenName": "Tiger", "type": "Cat" },
{ "givenName": "Princess", "type": "Cat" }
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{ "givenName": "Jake", "type": "Snake" }
]
}
],
"location": { "state": "NY", "county": "Manhattan", "city": "NY" },
"isRegistered": false
}
WHERE句で比較演算子を使用する簡単な例を見てみましょう。
このクエリのWHERE句では、(WHERE f.id = "WakefieldFamily")条件が指定され、IDがWakefieldFamilyと等しいドキュメントを取得します。
SELECT *
FROM f
WHERE f.id = "WakefieldFamily"
上記のクエリを実行すると、次の出力に示すように、WakefieldFamilyの完全なJSONドキュメントが返されます。
[
{
"id": "WakefieldFamily",
"parents": [
{
"familyName": "Wakefield",
"givenName": "Robin"
},
{
"familyName": "Miller",
"givenName": "Ben"
}
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{
"givenName": "Charlie Brown",
"type": "Dog"
},
{
"givenName": "Tiger",
"type": "Cat"
},
{
"givenName": "Princess",
"type": "Cat"
}
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{
"givenName": "Jake",
"type": "Snake"
}
]
}
],
"location": {
"state": "NY",
"county": "Manhattan",
"city": "NY"
},
"isRegistered": false,
"_rid": "Ic8LAJFujgECAAAAAAAAAA==",
"_ts": 1450541623,
"_self": "dbs/Ic8LAA==/colls/Ic8LAJFujgE=/docs/Ic8LAJFujgECAAAAAAAAAA==/",
"_etag": "\"00000500-0000-0000-0000-567582370000\"",
"_attachments": "attachments/"
}
]
クエリがグレードが5より大きい子データを取得する別の例を見てみましょう。
SELECT*
FROM Families.children[0] c
WHERE (c.grade > 5)
上記のクエリが実行されると、出力に示されているように、次のサブドキュメントが取得されます。
[
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{
"givenName": "Charlie Brown",
"type": "Dog"
},
{
"givenName": "Tiger",
"type": "Cat"
},
{
"givenName": "Princess",
"type": "Cat"
}
]
}
]
DocumentDB SQL-Betweenキーワード
BETWEENキーワードは、SQLのような値の範囲に対するクエリを表現するために使用されます。 BETWEENは、文字列または数値に対して使用できます。 DocumentDBとANSI SQLでBETWEENを使用する主な違いは、混合型のプロパティに対して範囲クエリを表現できることです。
たとえば、一部のドキュメントでは、数値として「グレード」があり、他のドキュメントでは文字列である可能性があります。 これらの場合、2つの異なるタイプの結果の比較は「未定義」であり、ドキュメントはスキップされます。
前の例の3つのドキュメントを考えてみましょう。 以下は AndersenFamily ドキュメントです。
{
"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
}
以下は SmithFamily ドキュメントです。
{
"id": "SmithFamily",
"parents": [
{ "familyName": "Smith", "givenName": "James" },
{ "familyName": "Curtis", "givenName": "Helen" }
],
"children": [
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"givenName": "John",
"gender": "male",
"grade": 7,
"pets": [
{ "givenName": "Tweetie", "type": "Bird" }
]
}
],
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
"isRegistered": true
}
以下は WakefieldFamily ドキュメントです。
{
"id": "WakefieldFamily",
"parents": [
{ "familyName": "Wakefield", "givenName": "Robin" },
{ "familyName": "Miller", "givenName": "Ben" }
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{ "givenName": "Charlie Brown", "type": "Dog" },
{ "givenName": "Tiger", "type": "Cat" },
{ "givenName": "Princess", "type": "Cat" }
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{ "givenName": "Jake", "type": "Snake" }
]
}
],
"location": { "state": "NY", "county": "Manhattan", "city": "NY" },
"isRegistered": false
}
クエリを実行して、最初の子供の成績が1〜5(両方を含む)であるすべての家族のドキュメントを返す例を見てみましょう。
以下は、BETWEENキーワードが使用され、次にAND論理演算子が使用されるクエリです。
SELECT *
FROM Families.children[0] c
WHERE c.grade BETWEEN 1 AND 5
上記のクエリを実行すると、次の出力が生成されます。
[
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"firstName": "Henriette Thaulow",
"gender": "female",
"grade": 5,
"pets": [
{
"givenName": "Fluffy",
"type": "Rabbit"
}
]
}
]
前の例の範囲外のグレードを表示するには、次のクエリに示すようにNOT BETWEENを使用します。
SELECT*
FROM Families.children[0] c
WHERE c.grade NOT BETWEEN 1 AND 5
このクエリが実行されるとき。 次の出力が生成されます。
[
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{
"givenName": "Charlie Brown",
"type": "Dog"
},
{
"givenName": "Tiger",
"type": "Cat"
},
{
"givenName": "Princess",
"type": "Cat"
}
]
}
]
DocumentDB SQL-Inキーワード
INキーワードを使用して、指定した値がリスト内のいずれかの値と一致するかどうかを確認できます。 IN演算子を使用すると、WHERE句に複数の値を指定できます。 INは、複数のOR句を連鎖することと同等です。
同様の3つのドキュメントは、以前の例で行われたと見なされます。 以下は AndersenFamily ドキュメントです。
{
"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
}
以下は SmithFamily ドキュメントです。
{
"id": "SmithFamily",
"parents": [
{ "familyName": "Smith", "givenName": "James" },
{ "familyName": "Curtis", "givenName": "Helen" }
],
"children": [
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"givenName": "John",
"gender": "male",
"grade": 7,
"pets": [
{ "givenName": "Tweetie", "type": "Bird" }
]
}
],
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
"isRegistered": true
}
以下は WakefieldFamily ドキュメントです。
{
"id": "WakefieldFamily",
"parents": [
{ "familyName": "Wakefield", "givenName": "Robin" },
{ "familyName": "Miller", "givenName": "Ben" }
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{ "givenName": "Charlie Brown", "type": "Dog" },
{ "givenName": "Tiger", "type": "Cat" },
{ "givenName": "Princess", "type": "Cat" }
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{ "givenName": "Jake", "type": "Snake" }
]
}
],
"location": { "state": "NY", "county": "Manhattan", "city": "NY" },
"isRegistered": false
}
簡単な例を見てみましょう。
以下は、familyNameが「Smith」またはWakefieldであるデータを取得するクエリです。
SELECT *
FROM Families.parents[0] f
WHERE f.familyName IN ('Smith', 'Wakefield')
上記のクエリを実行すると、次の出力が生成されます。
[
{
"familyName": "Wakefield",
"givenName": "Robin"
},
{
"familyName": "Smith",
"givenName": "James"
}
]
idが「SmithFamily」または「AndersenFamily」のいずれかであるすべてのファミリドキュメントが取得される別の簡単な例を考えてみましょう。 以下はクエリです。
SELECT*
FROM Families
WHERE Families.id IN ('SmithFamily', 'AndersenFamily')
上記のクエリを実行すると、次の出力が生成されます。
[
{
"id": "SmithFamily",
"parents": [
{
"familyName": "Smith",
"givenName": "James"
},
{
"familyName": "Curtis",
"givenName": "Helen"
}
],
"children": [
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"givenName": "John",
"gender": "male",
"grade": 7,
"pets": [
{
"givenName": "Tweetie",
"type": "Bird"
}
]
}
],
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
"isRegistered": true,
"_rid": "Ic8LAJFujgEDAAAAAAAAAA==",
"_ts": 1450541623,
"_self": "dbs/Ic8LAA==/colls/Ic8LAJFujgE=/docs/Ic8LAJFujgEDAAAAAAAAAA==/",
"_etag": "\"00000600-0000-0000-0000-567582370000\"",
"_attachments": "attachments/"
},
{
"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,
"_rid": "Ic8LAJFujgEEAAAAAAAAAA==",
"_ts": 1450541624,
"_self": "dbs/Ic8LAA==/colls/Ic8LAJFujgE=/docs/Ic8LAJFujgEEAAAAAAAAAA==/",
"_etag": "\"00000700-0000-0000-0000-567582380000\"",
"_attachments": "attachments/"
}
]
DocumentDB SQL-値キーワード
単一の値のみを返すことがわかっている場合、VALUEキーワードは、本格的なオブジェクトを作成するオーバーヘッドを回避することで、よりスリムな結果セットを生成するのに役立ちます。 VALUEキーワードは、JSON値を返す方法を提供します。
簡単な例を見てみましょう。
以下は、VALUEキーワードを使用したクエリです。
SELECT VALUE "Hello World, this is DocumentDB SQL Tutorial"
このクエリが実行されると、スカラー「Hello World、これはDocumentDB SQLチュートリアル」を返します。
[
"Hello World, this is DocumentDB SQL Tutorial"
]
別の例では、前の例の3つのドキュメントを考えてみましょう。
以下は AndersenFamily ドキュメントです。
{
"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
}
以下は SmithFamily ドキュメントです。
{
"id": "SmithFamily",
"parents": [
{ "familyName": "Smith", "givenName": "James" },
{ "familyName": "Curtis", "givenName": "Helen" }
],
"children": [
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"givenName": "John",
"gender": "male",
"grade": 7,
"pets": [
{ "givenName": "Tweetie", "type": "Bird" }
]
}
],
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
"isRegistered": true
}
以下は WakefieldFamily ドキュメントです。
{
"id": "WakefieldFamily",
"parents": [
{ "familyName": "Wakefield", "givenName": "Robin" },
{ "familyName": "Miller", "givenName": "Ben" }
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{ "givenName": "Charlie Brown", "type": "Dog" },
{ "givenName": "Tiger", "type": "Cat" },
{ "givenName": "Princess", "type": "Cat" }
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{ "givenName": "Jake", "type": "Snake" }
]
}
],
"location": { "state": "NY", "county": "Manhattan", "city": "NY" },
"isRegistered": false
}
以下はクエリです。
SELECT VALUE f.location
FROM Families f
このクエリが実行されると、位置ラベルなしで住所を返します。
[
{
"state": "NY",
"county": "Manhattan",
"city": "NY"
},
{
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
{
"state": "WA",
"county": "King",
"city": "Seattle"
}
]
VALUEキーワードなしで同じクエリを指定すると、ロケーションラベル付きの住所が返されます。 以下はクエリです。
SELECT f.location
FROM Families f
このクエリを実行すると、次の出力が生成されます。
[
{
"location": {
"state": "NY",
"county": "Manhattan",
"city": "NY"
}
},
{
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
}
},
{
"location": {
"state": "WA",
"county": "King",
"city": "Seattle"
}
}
]
DocumentDB SQL-句による順序
Microsoft Azure DocumentDBは、SQL over JSONドキュメントを使用したドキュメントのクエリをサポートしています。 クエリでORDER BY句を使用して、コレクション内のドキュメントを数字と文字列で並べ替えることができます。 句には、オプションのASC/DESC引数を含めて、結果を取得する必要がある順序を指定できます。
前の例と同じドキュメントを検討します。
以下は AndersenFamily ドキュメントです。
{
"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
}
以下は SmithFamily ドキュメントです。
{
"id": "SmithFamily",
"parents": [
{ "familyName": "Smith", "givenName": "James" },
{ "familyName": "Curtis", "givenName": "Helen" }
],
"children": [
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"givenName": "John",
"gender": "male",
"grade": 7,
"pets": [
{ "givenName": "Tweetie", "type": "Bird" }
]
}
],
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
"isRegistered": true
}
以下は WakefieldFamily ドキュメントです。
{
"id": "WakefieldFamily",
"parents": [
{ "familyName": "Wakefield", "givenName": "Robin" },
{ "familyName": "Miller", "givenName": "Ben" }
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{ "givenName": "Charlie Brown", "type": "Dog" },
{ "givenName": "Tiger", "type": "Cat" },
{ "givenName": "Princess", "type": "Cat" }
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{ "givenName": "Jake", "type": "Snake" }
]
}
],
"location": { "state": "NY", "county": "Manhattan", "city": "NY" },
"isRegistered": false
}
簡単な例を見てみましょう。
以下は、ORDER BYキーワードを含むクエリです。
SELECT f.id, f.children[0].givenName,f.children[0].grade
FROM Families f
ORDER BY f.children[0].grade
上記のクエリを実行すると、次の出力が生成されます。
[
{
"id": "SmithFamily",
"givenName": "Michelle",
"grade": 1
},
{
"id": "AndersenFamily",
"grade": 5
},
{
"id": "WakefieldFamily",
"givenName": "Jesse",
"grade": 6
}
]
別の簡単な例を考えてみましょう。
以下は、ORDER BYキーワードとDESCオプションキーワードを含むクエリです。
SELECT f.id, f.parents[0].familyName
FROM Families f
ORDER BY f.parents[0].familyName DESC
上記のクエリを実行すると、次の出力が生成されます。
[
{
"id": "WakefieldFamily",
"familyName": "Wakefield"
},
{
"id": "SmithFamily",
"familyName": "Smith"
},
{
"id": "AndersenFamily"
}
]
DocumentDB SQL-反復
DocumentDB SQLでは、MicrosoftはINキーワードで使用できる新しい構成を追加して、JSON配列の反復処理をサポートしています。 反復のサポートは、FROM句で提供されます。
前の例から同様の3つのドキュメントを再度検討します。
以下は AndersenFamily ドキュメントです。
{
"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
}
以下は SmithFamily ドキュメントです。
{
"id": "SmithFamily",
"parents": [
{ "familyName": "Smith", "givenName": "James" },
{ "familyName": "Curtis", "givenName": "Helen" }
],
"children": [
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"givenName": "John",
"gender": "male",
"grade": 7,
"pets": [
{ "givenName": "Tweetie", "type": "Bird" }
]
}
],
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
"isRegistered": true
}
以下は WakefieldFamily ドキュメントです。
{
"id": "WakefieldFamily",
"parents": [
{ "familyName": "Wakefield", "givenName": "Robin" },
{ "familyName": "Miller", "givenName": "Ben" }
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{ "givenName": "Charlie Brown", "type": "Dog" },
{ "givenName": "Tiger", "type": "Cat" },
{ "givenName": "Princess", "type": "Cat" }
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{ "givenName": "Jake", "type": "Snake" }
]
}
],
"location": { "state": "NY", "county": "Manhattan", "city": "NY" },
"isRegistered": false
}
FROM句にINキーワードを使用しない簡単な例を見てみましょう。
以下は、Familysコレクションからすべての親を返すクエリです。
SELECT *
FROM Families.parents
上記のクエリを実行すると、次の出力が生成されます。
[
[
{
"familyName": "Wakefield",
"givenName": "Robin"
},
{
"familyName": "Miller",
"givenName": "Ben"
}
],
[
{
"familyName": "Smith",
"givenName": "James"
},
{
"familyName": "Curtis",
"givenName": "Helen"
}
],
[
{
"firstName": "Thomas",
"relationship": "father"
},
{
"firstName": "Mary Kay",
"relationship": "mother"
}
]
]
上記の出力からわかるように、各ファミリの親は個別のJSON配列に表示されます。
同じ例を見てみましょう。ただし、今回はFROM句でINキーワードを使用します。
以下は、INキーワードを含むクエリです。
SELECT*
FROM c IN Families.parents
上記のクエリを実行すると、次の出力が生成されます。
[
{
"familyName": "Wakefield",
"givenName": "Robin"
},
{
"familyName": "Miller",
"givenName": "Ben"
},
{
"familyName": "Smith",
"givenName": "James"
},
{
"familyName": "Curtis",
"givenName": "Helen"
},
{
"firstName": "Thomas",
"relationship": "father"
},
{
"firstName": "Mary Kay",
"relationship": "mother"
}
{
"id": "WakefieldFamily",
"givenName": "Jesse",
"grade": 6
}
]
上記の例では、反復を使用すると、コレクション内の親に対して反復を実行するクエリの出力配列が異なることがわかります。 したがって、各ファミリのすべての親が単一の配列に追加されます。
DocumentDB SQL-結合
リレーショナルデータベースでは、Joins句を使用してデータベース内の2つ以上のテーブルのレコードを結合します。正規化されたスキーマを設計するときは、テーブル間で結合する必要が非常に重要です。 DocumentDBはスキーマフリードキュメントの非正規化データモデルを処理するため、DocumentDB SQLのJOINは「自己結合」と論理的に同等です。
前の例のように3つのドキュメントを考えてみましょう。
以下は AndersenFamily ドキュメントです。
{
"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
}
以下は SmithFamily ドキュメントです。
{
"id": "SmithFamily",
"parents": [
{ "familyName": "Smith", "givenName": "James" },
{ "familyName": "Curtis", "givenName": "Helen" }
],
"children": [
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"givenName": "John",
"gender": "male",
"grade": 7,
"pets": [
{ "givenName": "Tweetie", "type": "Bird" }
]
}
],
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
"isRegistered": true
}
以下は WakefieldFamily ドキュメントです。
{
"id": "WakefieldFamily",
"parents": [
{ "familyName": "Wakefield", "givenName": "Robin" },
{ "familyName": "Miller", "givenName": "Ben" }
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{ "givenName": "Charlie Brown", "type": "Dog" },
{ "givenName": "Tiger", "type": "Cat" },
{ "givenName": "Princess", "type": "Cat" }
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{ "givenName": "Jake", "type": "Snake" }
]
}
],
"location": { "state": "NY", "county": "Manhattan", "city": "NY" },
"isRegistered": false
}
JOIN句がどのように機能するかを理解するために例を見てみましょう。
ルートを子サブドキュメントに結合するクエリを次に示します。
SELECT f.id
FROM Families f
JOIN c IN f.children
上記のクエリを実行すると、次の出力が生成されます。
[
{
"id": "WakefieldFamily"
},
{
"id": "WakefieldFamily"
},
{
"id": "SmithFamily"
},
{
"id": "SmithFamily"
},
{
"id": "AndersenFamily"
}
]
上記の例では、結合はドキュメントルートと子サブルートの間で行われ、2つのJSONオブジェクト間のクロスプロダクトを作成します。 以下は注意すべき特定のポイントです-
- FROM句では、JOIN句は反復子です。
- 最初の2つのドキュメントWakefieldFamilyとSmithFamilyには2つの子が含まれているため、結果セットには、各子に対して個別のオブジェクトを生成するクロス積も含まれています。
- 3番目のドキュメントAndersenFamilyには1つの子しか含まれていないため、このドキュメントに対応するオブジェクトは1つだけです。
同じ例を見てみましょう。ただし、今回はJOIN句の理解を深めるために、子名も取得します。
ルートを子サブドキュメントに結合するクエリを次に示します。
SELECT
f.id AS familyName,
c.givenName AS childGivenName,
c.firstName AS childFirstName
FROM Families f
JOIN c IN f.children
上記のクエリを実行すると、次の出力が生成されます。
[
{
"familyName": "WakefieldFamily",
"childGivenName": "Jesse"
},
{
"familyName": "WakefieldFamily",
"childGivenName": "Lisa"
},
{
"familyName": "SmithFamily",
"childGivenName": "Michelle"
},
{
"familyName": "SmithFamily",
"childGivenName": "John"
},
{
"familyName": "AndersenFamily",
"childFirstName": "Henriette Thaulow"
}
]
DocumentDB SQL-エイリアス
リレーショナルデータベースでは、SQLエイリアスを使用して、テーブルまたは列見出しの名前を一時的に変更します。 同様に、DocumentDBでは、エイリアスを使用して、JSONドキュメント、サブドキュメント、オブジェクト、または任意のフィールドの名前を一時的に変更します。
名前の変更は一時的な変更であり、実際のドキュメントは変更されません。 基本的に、エイリアスはフィールド/ドキュメント名をより読みやすくするために作成されます。 エイリアスには、オプションのASキーワードが使用されます。
前の例で使用したものから3つの類似したドキュメントを考えてみましょう。
以下は AndersenFamily ドキュメントです。
{
"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
}
以下は SmithFamily ドキュメントです。
{
"id": "SmithFamily",
"parents": [
{ "familyName": "Smith", "givenName": "James" },
{ "familyName": "Curtis", "givenName": "Helen" }
],
"children": [
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"givenName": "John",
"gender": "male",
"grade": 7,
"pets": [
{ "givenName": "Tweetie", "type": "Bird" }
]
}
],
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
"isRegistered": true
}
以下は WakefieldFamily ドキュメントです。
{
"id": "WakefieldFamily",
"parents": [
{ "familyName": "Wakefield", "givenName": "Robin" },
{ "familyName": "Miller", "givenName": "Ben" }
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{ "givenName": "Charlie Brown", "type": "Dog" },
{ "givenName": "Tiger", "type": "Cat" },
{ "givenName": "Princess", "type": "Cat" }
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{ "givenName": "Jake", "type": "Snake" }
]
}
],
"location": { "state": "NY", "county": "Manhattan", "city": "NY" },
"isRegistered": false
}
エイリアスを説明する例を見てみましょう。
ルートを子サブドキュメントに結合するクエリを次に示します。 f.id AS familyName、c.givenName AS childGivenName、c.firstName AS childFirstNameなどのエイリアスがあります。
SELECT
f.id AS familyName,
c.givenName AS childGivenName,
c.firstName AS childFirstName
FROM Families f
JOIN c IN f.children
上記のクエリを実行すると、次の出力が生成されます。
[
{
"familyName": "WakefieldFamily",
"childGivenName": "Jesse"
},
{
"familyName": "WakefieldFamily",
"childGivenName": "Lisa"
},
{
"familyName": "SmithFamily",
"childGivenName": "Michelle"
},
{
"familyName": "SmithFamily",
"childGivenName": "John"
},
{
"familyName": "AndersenFamily",
"childFirstName": "Henriette Thaulow"
}
]
上記の出力は、ファイル名が変更されていることを示していますが、一時的な変更であり、元のドキュメントは変更されていません。
DocumentDB SQL-配列の作成
DocumentDB SQLでは、Microsoftは配列を簡単に作成できる重要な機能を追加しました。 つまり、クエリを実行すると、クエリの結果としてJSONオブジェクトに似たコレクションの配列が作成されます。
前の例と同じドキュメントを考えてみましょう。
以下は AndersenFamily ドキュメントです。
{
"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
}
以下は SmithFamily ドキュメントです。
{
"id": "SmithFamily",
"parents": [
{ "familyName": "Smith", "givenName": "James" },
{ "familyName": "Curtis", "givenName": "Helen" }
],
"children": [
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"givenName": "John",
"gender": "male",
"grade": 7,
"pets": [
{ "givenName": "Tweetie", "type": "Bird" }
]
}
],
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
"isRegistered": true
}
以下は WakefieldFamily ドキュメントです。
{
"id": "WakefieldFamily",
"parents": [
{ "familyName": "Wakefield", "givenName": "Robin" },
{ "familyName": "Miller", "givenName": "Ben" }
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{ "givenName": "Charlie Brown", "type": "Dog" },
{ "givenName": "Tiger", "type": "Cat" },
{ "givenName": "Princess", "type": "Cat" }
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{ "givenName": "Jake", "type": "Snake" }
]
}
],
"location": { "state": "NY", "county": "Manhattan", "city": "NY" },
"isRegistered": false
}
例を見てみましょう。
以下は、各ファミリのファミリ名と住所を返すクエリです。
SELECT f.id AS FamilyName,
[f.location.city, f.location.county, f.location.state] AS Address
FROM Families f
ご覧のように、市、郡および州のフィールドは角括弧で囲まれています。角括弧は配列を作成し、この配列の名前はAddressです。 上記のクエリを実行すると、次の出力が生成されます。
[
{
"FamilyName": "WakefieldFamily",
"Address": [
"NY",
"Manhattan",
"NY"
]
},
{
"FamilyName": "SmithFamily",
"Address": [
"Forest Hills",
"Queens",
"NY"
]
},
{
"FamilyName": "AndersenFamily",
"Address": [
"Seattle",
"King",
"WA"
]
}
]
市、郡、および州の情報は、上記の出力のAddress配列に追加されます。
DocumentDB SQL-スカラー式
DocumentDB SQLでは、SELECT句は定数、算術式、論理式などのスカラー式もサポートします。 通常、スカラークエリはコレクション内のドキュメントを実際にクエリするのではなく、式を評価するだけなので、めったに使用されません。 ただし、スカラー式クエリを使用して、クエリの基本、式の使用方法、JSONの作成方法を学習すると、これらの概念がコレクション内のドキュメントに対して実行する実際のクエリに直接適用されます。
複数のスカラークエリを含む例を見てみましょう。
クエリエクスプローラーで、実行するテキストのみを選択し、[実行]をクリックします。 これを最初に実行しましょう。
SELECT "Hello"
上記のクエリを実行すると、次の出力が生成されます。
[
{
"$1": "Hello"
}
]
この出力は少しわかりにくいかもしれませんので、分解してみましょう。
- 最初に、最後のデモで見たように、クエリ結果はJSON配列として返されるため、クエリ結果は常に角括弧で囲まれます。単一のドキュメントのみを返すこのようなスカラー式クエリの結果でもです。
- 1つのドキュメントを含む配列があり、そのドキュメントには、SELECTステートメントの1つの式に対する1つのプロパティがあります。
- SELECTステートメントはこのプロパティの名前を提供しないため、DocumentDBは$ 1を使用して名前を自動生成します。
- これは通常、私たちが望んでいるものではありません。このため、ASを使用してクエリ内の式のエイリアスを作成し、生成されたドキュメントのプロパティ名をこの例のように単語に設定します。
SELECT "Hello" AS word
上記のクエリを実行すると、次の出力が生成されます。
[
{
"word": "Hello"
}
]
同様に、以下は別の簡単なクエリです。
SELECT ((2 + 11 % 7)-2)/3
クエリは次の出力を取得します。
[
{
"$1": 1.3333333333333333
}
]
ネストされた配列と埋め込みオブジェクトを整形する別の例を見てみましょう。
SELECT
{
"words1":
["Hello", "World"],
"words2":
["How", "Are", "You?"]
} AS allWords
上記のクエリを実行すると、次の出力が生成されます。
[
{
"allWords": {
"words1": [
"Hello",
"World"
],
"words2": [
"How",
"Are",
"You?"
]
}
}
]
DocumentDB SQL-パラメーター化
リレーショナルデータベースでは、パラメーター化されたクエリは、プレースホルダーがパラメーターに使用され、パラメーター値が実行時に提供されるクエリです。 DocumentDBはパラメーター化されたクエリもサポートしており、パラメーター化されたクエリのパラメーターはおなじみの@表記で表現できます。 パラメーター化されたクエリを使用する最も重要な理由は、SQLインジェクション攻撃を回避することです。 また、ユーザー入力の堅牢な処理とエスケープを提供できます。
Net SDKを使用する例を見てみましょう。 以下は、コレクションを削除するコードです。.
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);
}
パラメーター化されたクエリの構築は次のとおりです。
var query = new SqlQuerySpec {
QueryText = "SELECT* FROM c WHERE c.id = @id",
Parameters = new SqlParameterCollection { new SqlParameter { Name =
"@id", Value = collectionId } }
};
collectionIdをハードコーディングしていないため、このメソッドを使用してコレクションを削除できます。 SQL Serverと同様に、パラメータ名の前に「@」記号を使用できます。
上記の例では、Idによって特定のコレクションを照会しています。Idパラメーターは、このSqlQuerySpecのパラメーターのプロパティに割り当てられたこのSqlParameterCollectionで定義されています。 次にSDKは、内部にcollectionIdが埋め込まれたDocumentDBの最終的なクエリ文字列を作成する作業を行います。 クエリを実行し、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 = 'earthquake'").AsEnumerable().First();
collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
"SELECT* FROM c WHERE c.id = 'myfirstdb'").AsEnumerable().First();
await DeleteCollection(client, "MyCollection1");
await DeleteCollection(client, "MyCollection2");
}
}
コードが実行されると、次の出力が生成されます。
*** *Delete Collection MyCollection1 in mydb* ***
Deleted collection MyCollection1 from database myfirstdb
*** *Delete Collection MyCollection2 in mydb* ** *
Deleted collection MyCollection2 from database myfirstdb
別の例を見てみましょう。 パラメーターとして姓と住所の状態を取得し、ユーザー入力に基づいてlastnameとlocation.stateのさまざまな値に対して実行するクエリを作成できます。
SELECT*
FROM Families f
WHERE f.lastName = @lastName AND f.location.state = @addressState
このリクエストは、次のコードに示すように、パラメーター化されたJSONクエリとしてDocumentDBに送信できます。
{
"query": "SELECT * FROM Families f WHERE f.lastName = @lastName AND
f.location.state = @addressState",
"parameters": [
{"name": "@lastName", "value": "Wakefield"},
{"name": "@addressState", "value": "NY"},
]
}
DocumentDB SQL-組み込み関数
DocumentDBは、クエリ内で使用できる一般的な操作のための組み込み関数のホストをサポートしています。 数学的計算を実行するための多くの関数があり、さまざまなスキーマを操作する際に非常に役立つ型チェック関数もあります。 これらの関数は、特定のプロパティが存在するかどうか、およびそれが数値か文字列か、ブール値かオブジェクトかをテストできます。
また、文字列を解析および操作するためのこれらの便利な関数、および配列を連結し、配列に特定の要素が含まれているかどうかをテストするなどの操作を可能にするいくつかの関数を取得します。
以下は、組み込み関数のさまざまなタイプです-
S.No. | Built-in Functions & Description |
---|---|
1 |
数学関数は、通常は引数として提供される入力値に基づいて計算を実行し、数値を返します。 |
2 |
型チェック関数を使用すると、SQLクエリ内の式の型をチェックできます。 |
3 |
文字列関数は、文字列の入力値に対して操作を実行し、文字列、数値、またはブール値を返します。 |
4 |
配列関数は、配列入力値に対して演算を実行し、数値、ブール値、配列値の形式で返します。 |
5 |
DocumentDBは、地理空間クエリのためのOpen Geospatial Consortium(OGC)組み込み関数もサポートしています。 |
DocumentDB SQL-LinqからSQLへの翻訳
DocumentDBでは、実際にSQLを使用してドキュメントを照会します。 .NET開発を行っている場合は、使用でき、LINQクエリから適切なSQLを生成できるLINQプロバイダーもあります。
サポートされているデータ型
DocumentDBでは、すべてのJSONプリミティブ型は、DocumentDB .NET SDKに含まれるLINQプロバイダーでサポートされています。
- 数値
- ブール値
- ひも
- Null
サポートされている式
次のスカラー式は、DocumentDB .NET SDKに含まれているLINQプロバイダーでサポートされています。
- 定数値-プリミティブデータ型の定数値を含みます。
- プロパティ/配列インデックス式-式は、オブジェクトまたは配列要素のプロパティを参照します。
- 算術式-数値およびブール値に関する一般的な算術式が含まれます。
- 文字列比較式-文字列値と一定の文字列値の比較が含まれます。
- オブジェクト/配列作成式-複合値型または匿名型のオブジェクト、またはそのようなオブジェクトの配列を返します。 これらの値はネストできます。
サポートされているLINQオペレーター
これは、DocumentDB .NET SDKに含まれているLINQプロバイダーでサポートされているLINQオペレーターのリストです。
- 選択-投影は、オブジェクト構築を含むSQL SELECTに変換されます。
- Where -フィルタはSQL WHEREに変換され、&&、||間の変換をサポートします。そして! SQLオペレーターに。
- SelectMany -SQL JOIN句への配列の巻き戻しを許可します。 式をチェーン/ネストして、配列要素をフィルタリングするために使用できます。
- OrderByおよびOrderByDescending -ORDER BYの昇順/降順に変換します。
- CompareTo -範囲比較に変換します。 .NETでは比較できないため、一般的に文字列に使用されます。
- Take -クエリの結果を制限するためにSQL TOPに変換します。
- * Math関数*-.NETのAbs、Acos、Asin、Atan、Ceiling、Cos、Exp、Floor、Log、Log10、Pow、Round、Sign、Sin、Sqrt、Tan、Truncateから同等のSQLビルトインへの変換をサポート関数。
- 文字列関数-.NETのConcat、Contains、EndsWith、IndexOf、Count、ToLower、TrimStart、Replace、Reverse、TrimEnd、StartsWith、SubString、ToUpperから同等のSQL組み込み関数への変換をサポートします。
- 配列関数-.NETのConcat、Contains、Countから同等のSQL組み込み関数への変換をサポートします。
- 地理空間拡張関数-スタブメソッドDistance、Within、IsValid、およびIsValidDetailedから同等のSQL組み込み関数への変換をサポートします。
- User-Defined Extension Function -スタブメソッドUserDefinedFunctionProvider.Invokeから対応するユーザー定義関数への変換をサポートします。
- その他-合体演算子と条件演算子の翻訳をサポートします。 コンテキストに応じて、ContainsをString CONTAINS、ARRAY_CONTAINS、またはSQL INに変換できます。
新規顧客1
Net SDKを使用する例を見てみましょう。 以下は、この例で検討する3つのドキュメントです。.
{
"name": "New Customer 1",
"address": {
"addressType": "Main Office",
"addressLine1": "123 Main Street",
"location": {
"city": "Brooklyn",
"stateProvinceName": "New York"
},
"postalCode": "11229",
"countryRegionName": "United States"
},
}
新規顧客2
{
"name": "New Customer 2",
"address": {
"addressType": "Main Office",
"addressLine1": "678 Main Street",
"location": {
"city": "London",
"stateProvinceName": " London "
},
"postalCode": "11229",
"countryRegionName": "United Kingdom"
},
}
新規顧客3
{
"name": "New Customer 3",
"address": {
"addressType": "Main Office",
"addressLine1": "12 Main Street",
"location": {
"city": "Brooklyn",
"stateProvinceName": "New York"
},
"postalCode": "11229",
"countryRegionName": "United States"
},
}
以下は、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} US 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句を生成します。
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();
QueryDocumentsWithLinq(client);
}
}
上記のコードが実行されると、次の出力が生成されます。
*** *Query Documents (LINQ)* ***
Quering for US customers (LINQ)
Found 2 US customers
Id: 7e9ad4fa-c432-4d1a-b120-58fd7113609f; Name: New Customer 1; City: Brooklyn
Id: 34e9873a-94c8-4720-9146-d63fb7840fad; Name: New Customer 1; City: Brooklyn
DocumentDB SQL-JavaScript統合
最近では、JavaScriptはブラウザだけでなくどこにでもあります。 DocumentDBは、JavaScriptを現代のT-SQLの一種として受け入れ、データベースエンジン内でJavaScriptロジックのネイティブなトランザクション実行をサポートします。 DocumentDBは、ストアドプロシージャとトリガーに関して、コレクション上でJavaScriptベースのアプリケーションロジックを直接実行するためのプログラミングモデルを提供します。
簡単なストアプロシージャを作成する例を見てみましょう。 手順は次のとおりです-
- ステップ1 *-新しいコンソールアプリケーションを作成します。
- ステップ2 *-NuGetから.NET SDKに追加します。 ここでは.NET SDKを使用しています。つまり、ストアドプロシージャを作成、実行、および削除するためのC#コードを記述しますが、ストアドプロシージャ自体はJavaScriptで記述されます。
- ステップ3 *-ソリューションエクスプローラーでプロジェクトを右クリックします。
- ステップ4 *-ストアドプロシージャ用の新しいJavaScriptファイルを追加し、HelloWorldStoreProce.jsを呼び出します
すべてのストアドプロシージャはJavaScript関数であるため、新しい関数を作成し、当然この関数に HelloWorldStoreProce という名前を付けます。 関数に名前を付けてもかまいません。 DocumentDBは、このストアドプロシージャを、作成時に指定したIDによってのみ参照します。
function HelloWorldStoreProce() {
var context = getContext();
var response = context.getResponse();
response.setBody('Hello, and welcome to DocumentDB!');
}
ストアドプロシージャは、コンテキストから応答オブジェクトを取得し、その setBody メソッドを呼び出して呼び出し元に文字列を返すだけです。 C#コードでは、ストアドプロシージャを作成し、実行してから削除します。
ストアドプロシージャはコレクションごとにスコープされるため、ストアドプロシージャを作成するにはコレクションのSelfLinkが必要です。
ステップ5 *-最初に *myfirstdb データベースを照会し、次に MyCollection コレクションを照会します。
ストアドプロシージャの作成は、DocumentDBの他のリソースの作成と同じです。
private async static Task SimpleStoredProcDemo() {
var endpoint = "https://azuredocdbdemo.documents.azure.com:443/";
var masterKey =
"BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
using (var client = new DocumentClient(new Uri(endpoint), masterKey)) {
//Get database
Database database = client
.CreateDatabaseQuery("SELECT *FROM c WHERE c.id = 'myfirstdb'")
.AsEnumerable()
.First();
//Get collection
DocumentCollection collection = client
.CreateDocumentCollectionQuery(database.CollectionsLink, "SELECT* FROM
c WHERE c.id = 'MyCollection'")
.AsEnumerable()
.First();
//Create stored procedure
var sprocBody = File.ReadAllText(@"..\..\HelloWorldStoreProce.js");
var sprocDefinition = new StoredProcedure {
Id = "HelloWorldStoreProce",
Body = sprocBody
};
StoredProcedure sproc = await client.
CreateStoredProcedureAsync(collection.SelfLink, sprocDefinition);
Console.WriteLine("Created stored procedure {0} ({1})",
sproc.Id, sproc.ResourceId);
//Execute stored procedure
var result = await client.ExecuteStoredProcedureAsync(sproc.SelfLink);
Console.WriteLine("Executed stored procedure; response = {0}", result.Response);
//Delete stored procedure
await client.DeleteStoredProcedureAsync(sproc.SelfLink);
Console.WriteLine("Deleted stored procedure {0} ({1})",
sproc.Id, sproc.ResourceId);
}
}
ステップ6 *-最初に新しいリソースのIDで定義オブジェクトを作成し、次に *DocumentClient オブジェクトでCreateメソッドの1つを呼び出します。 ストアドプロシージャの場合、定義にはIdとサーバーに送信する実際のJavaScriptコードが含まれます。
ステップ7 *- *File.ReadAllText を呼び出して、JSファイルからストアドプロシージャコードを抽出します。
- ステップ8 *-ストアドプロシージャコードを定義オブジェクトのbodyプロパティに割り当てます。
DocumentDBに関する限り、ここで定義で指定するIdは、実際にJavaScript関数に名前を付けるかどうかに関係なく、ストアドプロシージャの名前です。
それでも、ストアドプロシージャやその他のサーバー側オブジェクトを作成するときは、JavaScript関数に名前を付け、それらの関数名がDocumentDBの定義で設定したIDと一致することをお勧めします。
ステップ9 *- *CreateStoredProcedureAsync を呼び出し、 MyCollection コレクションとストアドプロシージャ定義の SelfLink を渡します。 これにより、DocumentDBが割り当てたストアドプロシージャと ResourceId が作成されます。
ステップ10 *-ストアドプロシージャを呼び出します。 *ExecuteStoredProcedureAsync は、ストアドプロシージャによって返される値の予期されるデータ型に設定する型パラメーターを取ります。動的パラメーターを返す場合は、オブジェクトとして単純に指定できます。 これは、実行時にプロパティがバインドされるオブジェクトです。
この例では、ストアドプロシージャが文字列を返しているだけであるため、 ExecuteStoredProcedureAsync <string> を呼び出します。
以下は、Program.csファイルの完全な実装です。
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DocumentDBStoreProce {
class Program {
private static void Main(string[] args) {
Task.Run(async () => {
await SimpleStoredProcDemo();
}).Wait();
}
private async static Task SimpleStoredProcDemo() {
var endpoint = "https://azuredocdbdemo.documents.azure.com:443/";
var masterKey =
"BBhjI0gxdVPdDbS4diTjdloJq7Fp4L5RO/StTt6UtEufDM78qM2CtBZWbyVwFPSJIm8AcfDu2O+AfV T+TYUnBQ==";
using (var client = new DocumentClient(new Uri(endpoint), masterKey)) {
//Get database
Database database = client
.CreateDatabaseQuery("SELECT *FROM c WHERE c.id = 'myfirstdb'")
.AsEnumerable()
.First();
//Get collection
DocumentCollection collection = client
.CreateDocumentCollectionQuery(database.CollectionsLink,
"SELECT* FROM c WHERE c.id = 'MyCollection'")
.AsEnumerable()
.First();
//Create stored procedure
var sprocBody = File.ReadAllText(@"..\..\HelloWorldStoreProce.js");
var sprocDefinition = new StoredProcedure {
Id = "HelloWorldStoreProce",
Body = sprocBody
};
StoredProcedure sproc = await client
.CreateStoredProcedureAsync(collection.SelfLink, sprocDefinition);
Console.WriteLine("Created stored procedure {0} ({1})", sproc
.Id, sproc.ResourceId);
//Execute stored procedure
var result = await client
.ExecuteStoredProcedureAsync<string>(sproc.SelfLink);
Console.WriteLine("Executed stored procedure; response = {0}",
result.Response);
//Delete stored procedure
await client.DeleteStoredProcedureAsync(sproc.SelfLink);
Console.WriteLine("Deleted stored procedure {0} ({1})",
sproc.Id, sproc.ResourceId);
}
}
}
}
上記のコードが実行されると、次の出力が生成されます。
Created stored procedure HelloWorldStoreProce (Ic8LAMEUVgACAAAAAAAAgA==)
Executed stored procedure; response = Hello, and welcome to DocumentDB!
上記の出力に見られるように、応答プロパティには、ストアドプロシージャによって返された「Hello、and welcome to DocumentDB!」があります。
DocumentDB SQL-ユーザー定義関数
DocumentDB SQLは、ユーザー定義関数(UDF)のサポートを提供します。 UDFは、ユーザーが記述できるJavaScript関数の一種に過ぎず、これらは期待どおりに機能します。 UDFを作成して、クエリで参照できるカスタムビジネスロジックでクエリ言語を拡張できます。
DocumentDB SQL構文は、これらのUDFを使用してカスタムアプリケーションロジックをサポートするように拡張されています。 UDFはDocumentDBに登録し、SQLクエリの一部として参照できます。
この例では、次の3つのドキュメントを考えてみましょう。
*AndersenFamily* ドキュメントは次のとおりです。
{
"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
}
*SmithFamily* ドキュメントは次のとおりです。
{
"id": "SmithFamily",
"parents": [
{ "familyName": "Smith", "givenName": "James" },
{ "familyName": "Curtis", "givenName": "Helen" }
],
"children": [
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"givenName": "John",
"gender": "male",
"grade": 7,
"pets": [
{ "givenName": "Tweetie", "type": "Bird" }
]
}
],
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
"isRegistered": true
}
*WakefieldFamily* ドキュメントは次のとおりです。
{
"id": "WakefieldFamily",
"parents": [
{ "familyName": "Wakefield", "givenName": "Robin" },
{ "familyName": "Miller", "givenName": "Ben" }
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{ "givenName": "Charlie Brown", "type": "Dog" },
{ "givenName": "Tiger", "type": "Cat" },
{ "givenName": "Princess", "type": "Cat" }
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{ "givenName": "Jake", "type": "Snake" }
]
}
],
"location": { "state": "NY", "county": "Manhattan", "city": "NY" },
"isRegistered": false
}
簡単なUDFを作成する例を見てみましょう。
以下は、 CreateUserDefinedFunctions の実装です。
private async static Task CreateUserDefinedFunctions(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("*** *Create User Defined Functions* ***");
Console.WriteLine();
await CreateUserDefinedFunction(client, "udfRegEx");
}
udfRegExがあり、CreateUserDefinedFunctionでローカルファイルからJavaScriptコードを取得します。 次のコードに示すように、新しいUDFの定義オブジェクトを作成し、コレクションのSelfLinkおよびudfDefinitionオブジェクトを使用してCreateUserDefinedFunctionAsyncを呼び出します。
private async static Task<UserDefinedFunction>
CreateUserDefinedFunction(DocumentClient client, string udfId) {
var udfBody = File.ReadAllText(@"..\..\Server\" + udfId + ".js");
var udfDefinition = new UserDefinedFunction {
Id = udfId,
Body = udfBody
};
var result = await client
.CreateUserDefinedFunctionAsync(_collection.SelfLink, udfDefinition);
var udf = result.Resource;
Console.WriteLine("Created user defined function {0}; RID: {1}",
udf.Id, udf.ResourceId);
return udf;
}
結果のリソースプロパティから新しいUDFを取得し、呼び出し元に返します。 既存のUDFを表示するための ViewUserDefinedFunctions の実装は次のとおりです。 CreateUserDefinedFunctionQuery を呼び出し、通常どおりループします。
private static void ViewUserDefinedFunctions(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("*** *View UDFs* ***");
Console.WriteLine();
var udfs = client
.CreateUserDefinedFunctionQuery(_collection.UserDefinedFunctionsLink)
.ToList();
foreach (var udf in udfs) {
Console.WriteLine("User defined function {0}; RID: {1}", udf.Id, udf.ResourceId);
}
}
DocumentDB SQLには、部分文字列または正規表現を検索するための組み込み関数が用意されていないため、次の小さなワンライナーがJavaScript関数であるこのギャップを埋めます。
function udfRegEx(input, regex) {
return input.match(regex);
}
最初のパラメーターの入力文字列を指定すると、JavaScriptの組み込み正規表現サポートを使用して、2番目のパラメーターのパターンマッチング文字列を。 match に渡します。 サブストリングクエリを実行して、 lastName プロパティにAndersenという単語が含まれるすべてのストアを検索できます。
private static void Execute_udfRegEx(DocumentClient client) {
var sql = "SELECT c.name FROM c WHERE udf.udfRegEx(c.lastName, 'Andersen') != null";
Console.WriteLine();
Console.WriteLine("Querying for Andersen");
var documents = client.CreateDocumentQuery(_collection.SelfLink, sql).ToList();
Console.WriteLine("Found {0} Andersen:", documents.Count);
foreach (var document in documents) {
Console.WriteLine("Id: {0}, Name: {1}", document.id, document.lastName);
}
}
すべてのUDF参照を接頭辞 udf で修飾する必要があることに注意してください。 通常のクエリと同様に、SQLを CreateDocumentQuery に渡しました。 最後に、 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 = 'Families'").AsEnumerable().First();
await CreateUserDefinedFunctions(client);
ViewUserDefinedFunctions(client);
Execute_udfRegEx(client);
}
}
上記のコードが実行されると、次の出力が生成されます。
*** *Create User Defined Functions* ***
Created user defined function udfRegEx; RID: kV5oANVXnwAlAAAAAAAAYA==
*** *View UDFs* ***
User defined function udfRegEx; RID: kV5oANVXnwAlAAAAAAAAYA==
Querying for Andersen
Found 1 Andersen:
Id: AndersenFamily, Name: Andersen
DocumentDB SQL-複合SQLクエリ
- 複合クエリ*を使用すると、既存のクエリからのデータを結合し、フィルター、集計などを適用してから、結合されたデータセットを示すレポート結果を表示できます。 複合クエリは、既存のクエリに関する複数レベルの関連情報を取得し、結合されたデータを単一のフラット化されたクエリ結果として表示します。
複合クエリを使用すると、次のオプションもあります-
- ユーザーの属性選択に基づいて、不要なテーブルとフィールドを削除するには、SQLプルーニングオプションを選択します。
- ORDER BYおよびGROUP BY句を設定します。
- 複合クエリの結果セットに対するフィルターとしてWHERE句を設定します。
上記の演算子を構成して、より強力なクエリを作成できます。 DocumentDBはネストされたコレクションをサポートしているため、構成は連結またはネストできます。
この例の次のドキュメントを考えてみましょう。
*AndersenFamily* ドキュメントは次のとおりです。
{
"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
}
*SmithFamily* ドキュメントは次のとおりです。
{
"id": "SmithFamily",
"parents": [
{ "familyName": "Smith", "givenName": "James" },
{ "familyName": "Curtis", "givenName": "Helen" }
],
"children": [
{
"givenName": "Michelle",
"gender": "female",
"grade": 1
},
{
"givenName": "John",
"gender": "male",
"grade": 7,
"pets": [
{ "givenName": "Tweetie", "type": "Bird" }
]
}
],
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
},
"isRegistered": true
}
*WakefieldFamily* ドキュメントは次のとおりです。
{
"id": "WakefieldFamily",
"parents": [
{ "familyName": "Wakefield", "givenName": "Robin" },
{ "familyName": "Miller", "givenName": "Ben" }
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{ "givenName": "Charlie Brown", "type": "Dog" },
{ "givenName": "Tiger", "type": "Cat" },
{ "givenName": "Princess", "type": "Cat" }
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{ "givenName": "Jake", "type": "Snake" }
]
}
],
"location": { "state": "NY", "county": "Manhattan", "city": "NY" },
"isRegistered": false
}
連結クエリの例を見てみましょう。
以下は、最初の子 givenName がMichelleである家族のIDと場所を取得するクエリです。
SELECT f.id,f.location
FROM Families f
WHERE f.children[0].givenName = "Michelle"
上記のクエリを実行すると、次の出力が生成されます。
[
{
"id": "SmithFamily",
"location": {
"state": "NY",
"county": "Queens",
"city": "Forest Hills"
}
}
]
連結クエリの別の例を考えてみましょう。
以下は、最初の子が3を超えるすべてのドキュメントを返すクエリです。
SELECT *
FROM Families f
WHERE ({grade: f.children[0].grade}.grade > 3)
上記のクエリを実行すると、次の出力が生成されます。
[
{
"id": "WakefieldFamily",
"parents": [
{
"familyName": "Wakefield",
"givenName": "Robin"
},
{
"familyName": "Miller",
"givenName": "Ben"
}
],
"children": [
{
"familyName": "Merriam",
"givenName": "Jesse",
"gender": "female",
"grade": 6,
"pets": [
{
"givenName": "Charlie Brown",
"type": "Dog"
},
{
"givenName": "Tiger",
"type": "Cat"
},
{
"givenName": "Princess",
"type": "Cat"
}
]
},
{
"familyName": "Miller",
"givenName": "Lisa",
"gender": "female",
"grade": 3,
"pets": [
{
"givenName": "Jake",
"type": "Snake"
}
]
}
],
"location": {
"state": "NY",
"county": "Manhattan",
"city": "NY"
},
"isRegistered": false,
"_rid": "Ic8LAJFujgECAAAAAAAAAA==",
"_ts": 1450541623,
"_self": "dbs/Ic8LAA==/colls/Ic8LAJFujgE=/docs/Ic8LAJFujgECAAAAAAAAAA==/",
"_etag": "\"00000500-0000-0000-0000-567582370000\"",
"_attachments": "attachments/"
},
{
"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,
"_rid": "Ic8LAJFujgEEAAAAAAAAAA==",
"_ts": 1450541624,
"_self": "dbs/Ic8LAA==/colls/Ic8LAJFujgE=/docs/Ic8LAJFujgEEAAAAAAAAAA==/",
"_etag": "\"00000700-0000-0000-0000-567582380000\"",
"_attachments": "attachments/"
}
]
ネストされたクエリの*例*を見てみましょう。
以下は、すべての親を繰り返し、 familyName がSmithであるドキュメントを返すクエリです。
SELECT *
FROM p IN Families.parents
WHERE p.familyName = "Smith"
上記のクエリを実行すると、次の出力が生成されます。
[
{
"familyName": "Smith",
"givenName": "James"
}
]
ネストされたクエリの*別の例*を考えてみましょう。
以下は、すべての familyName を返すクエリです。
SELECT VALUE p.familyName
FROM Families f
JOIN p IN f.parents
上記のクエリを実行すると、次の出力が生成されます。
[
"Wakefield",
"Miller",
"Smith",
"Curtis"
]