DocumentDB SQL — Обзор
DocumentDB — это новейшая платформа Microsoft NoSQL для базы данных документов, которая работает на Azure. В этом руководстве мы узнаем все о запросах документов с использованием специальной версии SQL, поддерживаемой DocumentDB.
NoSQL Document Database
DocumentDB является новейшей базой документов Microsoft NoSQL, однако, когда мы говорим о базе данных документов NoSQL, что именно мы подразумеваем под NoSQL, и базой данных документов?
-
SQL означает язык структурированных запросов, который является традиционным языком запросов для реляционных баз данных. SQL часто приравнивают к реляционным базам данных.
-
Действительно, более полезно думать о базе данных NoSQL как о нереляционной базе данных, поэтому NoSQL действительно означает нереляционную.
SQL означает язык структурированных запросов, который является традиционным языком запросов для реляционных баз данных. SQL часто приравнивают к реляционным базам данных.
Действительно, более полезно думать о базе данных NoSQL как о нереляционной базе данных, поэтому NoSQL действительно означает нереляционную.
Существуют различные типы баз данных NoSQL, которые включают хранилища значений ключей, такие как —
- Azure Table Storage
- Основанные на колонках магазины, такие как Кассандра
- Графовые базы данных, такие как NEO4
- Базы данных документов, такие как MongoDB и Azure DocumentDB
Почему синтаксис SQL?
Поначалу это может звучать странно, но в DocumentDB, которая является базой данных NoSQL, мы выполняем запросы с использованием SQL. Как упоминалось выше, это специальная версия SQL, основанная на семантике JSON и JavaScript.
-
SQL — это просто язык, но он также очень популярен, он богат и выразителен. Таким образом, определенно представляется хорошей идеей использовать некоторый диалект SQL, а не придумывать совершенно новый способ выражения запросов, который нам необходимо изучить, если вы хотите получить документы из своей базы данных.
-
SQL предназначен для реляционных баз данных, а DocumentDB является нереляционной базой документов. Команда DocumentDB фактически адаптировала синтаксис SQL для нереляционного мира баз данных документов, и это то, что подразумевается под внедрением SQL в JSON и JavaScript.
-
Язык по-прежнему читается как знакомый SQL, но все семантика основана на документах JSON без схемы, а не на реляционных таблицах. В DocumentDB мы будем работать с типами данных JavaScript, а не с типами данных SQL. Мы будем знакомы с SELECT, FROM, WHERE и т. Д., Но с типами JavaScript, которые ограничены числами и строками, объекты, массивы, логические и нулевые значения намного меньше, чем широкий диапазон типов данных SQL.
-
Точно так же выражения оцениваются как выражения JavaScript, а не как форма T-SQL. Например, в мире денормализованных данных мы имеем дело не со строками и столбцами, а с документами без схемы с иерархическими структурами, которые содержат вложенные массивы и объекты.
SQL — это просто язык, но он также очень популярен, он богат и выразителен. Таким образом, определенно представляется хорошей идеей использовать некоторый диалект SQL, а не придумывать совершенно новый способ выражения запросов, который нам необходимо изучить, если вы хотите получить документы из своей базы данных.
SQL предназначен для реляционных баз данных, а DocumentDB является нереляционной базой документов. Команда DocumentDB фактически адаптировала синтаксис SQL для нереляционного мира баз данных документов, и это то, что подразумевается под внедрением SQL в JSON и JavaScript.
Язык по-прежнему читается как знакомый SQL, но все семантика основана на документах JSON без схемы, а не на реляционных таблицах. В DocumentDB мы будем работать с типами данных JavaScript, а не с типами данных SQL. Мы будем знакомы с SELECT, FROM, WHERE и т. Д., Но с типами JavaScript, которые ограничены числами и строками, объекты, массивы, логические и нулевые значения намного меньше, чем широкий диапазон типов данных SQL.
Точно так же выражения оцениваются как выражения JavaScript, а не как форма T-SQL. Например, в мире денормализованных данных мы имеем дело не со строками и столбцами, а с документами без схемы с иерархическими структурами, которые содержат вложенные массивы и объекты.
Как работает SQL?
Команда DocumentDB ответила на этот вопрос несколькими инновационными способами. Немногие из них перечислены ниже:
-
Во-первых, предполагая, что вы не изменили поведение по умолчанию для автоматической индексации каждого свойства в документе, вы можете использовать пунктирную нотацию в своих запросах, чтобы найти путь к любому свойству, независимо от того, насколько глубоко оно вложено в документ.
-
Вы также можете выполнить соединение внутри документа, в котором вложенные элементы массива соединяются со своим родительским элементом в документе способом, очень похожим на способ, которым выполняется соединение между двумя таблицами в реляционном мире.
-
Ваши запросы могут возвращать документы из базы данных в том виде, в каком они есть, или вы можете проецировать любую произвольную фигуру JSON по своему усмотрению, основываясь на том количестве данных документа, которое вам нужно.
-
SQL в DocumentDB поддерживает многие из общих операторов, в том числе —
-
Арифметические и побитовые операции
-
И и ИЛИ логика
-
Равенство и диапазон сравнения
-
Конкатенация строк
-
-
Язык запросов также поддерживает множество встроенных функций.
Во-первых, предполагая, что вы не изменили поведение по умолчанию для автоматической индексации каждого свойства в документе, вы можете использовать пунктирную нотацию в своих запросах, чтобы найти путь к любому свойству, независимо от того, насколько глубоко оно вложено в документ.
Вы также можете выполнить соединение внутри документа, в котором вложенные элементы массива соединяются со своим родительским элементом в документе способом, очень похожим на способ, которым выполняется соединение между двумя таблицами в реляционном мире.
Ваши запросы могут возвращать документы из базы данных в том виде, в каком они есть, или вы можете проецировать любую произвольную фигуру JSON по своему усмотрению, основываясь на том количестве данных документа, которое вам нужно.
SQL в DocumentDB поддерживает многие из общих операторов, в том числе —
Арифметические и побитовые операции
И и ИЛИ логика
Равенство и диапазон сравнения
Конкатенация строк
Язык запросов также поддерживает множество встроенных функций.
DocumentDB SQL — Выбрать пункт
На портале Azure есть Query Explorer, который позволяет нам выполнять любые SQL-запросы к нашей базе данных DocumentDB. Мы будем использовать Query Explorer, чтобы продемонстрировать множество различных возможностей и возможностей языка запросов, начиная с самого простого запроса.
Шаг 1. Откройте портал Azure и в блейде базы данных щелкните блейд Query Explorer.
Помните, что запросы выполняются в рамках коллекции, поэтому Query Explorer позволяет нам выбрать коллекцию в этом раскрывающемся списке. Мы оставим это в нашей коллекции Семей, которая содержит три документа. Давайте рассмотрим эти три документа в этом примере.
Ниже приводится документ 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 }
Query Explorer открывается с этим простым запросом SELECT * FROM c, который просто извлекает все документы из коллекции. Несмотря на простоту, он все же сильно отличается от эквивалентного запроса в реляционной базе данных.
Шаг 2 — В реляционных базах данных SELECT * означает возврат всех столбцов в DocumentDB. Это означает, что вы хотите, чтобы каждый документ в вашем результате возвращался в точности так, как он хранится в базе данных.
Но когда вы выбираете конкретные свойства и выражения вместо простой выдачи SELECT *, тогда вы проецируете новую фигуру, которую вы хотите для каждого документа в результате.
Шаг 3 — Нажмите «Выполнить», чтобы выполнить запрос, и откройте колонку «Результаты».
Как видно, семейство WakefieldFamily, SmithFamily и AndersonFamily извлекаются.
Ниже приведены три документа, которые были получены в результате запроса SELECT * FROM c .
[ { "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_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 должен оценивать указанные условия как «истинные», чтобы учитываться для результата. Если данное условие выполнено, только тогда оно возвращает конкретные данные в форме документа (ов) JSON. Мы можем использовать предложение WHERE для фильтрации записей и выборки только необходимых записей.
Мы рассмотрим те же три документа в этом примере. Ниже приводится документ 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"
Когда вышеуказанный запрос будет выполнен, он вернет полный документ JSON для 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, "_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
Ниже приведен список всех операторов сравнения, доступных в грамматике SQL DocumentDB.
S.No. | Операторы и описание |
---|---|
1 |
знак равно Проверяет, равны ли значения двух операндов или нет. Если да, то условие становится истинным. |
2 |
знак равно Проверяет, равны ли значения двух операндов или нет. Если значения не равны, условие становится истинным. |
3 |
<> Проверяет, равны ли значения двух операндов или нет. Если значения не равны, условие становится истинным. |
4 |
> Проверяет, больше ли значение левого операнда, чем значение правого операнда. Если да, то условие становится истинным. |
5 |
< Проверяет, меньше ли значение левого операнда, чем значение правого операнда. Если да, то условие становится истинным. |
6 |
> = Проверяет, больше ли значение левого операнда или равно значению правого операнда. Если да, то условие становится истинным. |
7 |
<= Проверяет, меньше ли значение левого операнда или равно значению правого операнда. Если да, то условие становится истинным. |
знак равно
Проверяет, равны ли значения двух операндов или нет. Если да, то условие становится истинным.
знак равно
Проверяет, равны ли значения двух операндов или нет. Если значения не равны, условие становится истинным.
<>
Проверяет, равны ли значения двух операндов или нет. Если значения не равны, условие становится истинным.
>
Проверяет, больше ли значение левого операнда, чем значение правого операнда. Если да, то условие становится истинным.
<
Проверяет, меньше ли значение левого операнда, чем значение правого операнда. Если да, то условие становится истинным.
> =
Проверяет, больше ли значение левого операнда или равно значению правого операнда. Если да, то условие становится истинным.
<=
Проверяет, меньше ли значение левого операнда или равно значению правого операнда. Если да, то условие становится истинным.
Логические операторы SQL
Ниже приведен список всех логических операторов, доступных в грамматике SQL DocumentDB.
S.No. | Операторы и описание |
---|---|
1 |
А ТАКЖЕ Оператор AND допускает существование нескольких условий в предложении WHERE оператора SQL. |
2 |
МЕЖДУ Оператор BETWEEN используется для поиска значений, которые находятся в пределах набора значений, учитывая минимальное значение и максимальное значение. |
3 |
В Оператор IN используется для сравнения значения со списком литеральных значений, которые были указаны. |
4 |
ИЛИ ЖЕ Оператор OR используется для объединения нескольких условий в предложении WHERE оператора SQL. |
5 |
НЕ Оператор NOT меняет значение логического оператора, с которым он используется. Например, NOT EXISTS, NOT BETWEEN, NOT IN и т. Д. Это оператор отрицания. |
А ТАКЖЕ
Оператор AND допускает существование нескольких условий в предложении WHERE оператора SQL.
МЕЖДУ
Оператор BETWEEN используется для поиска значений, которые находятся в пределах набора значений, учитывая минимальное значение и максимальное значение.
В
Оператор IN используется для сравнения значения со списком литеральных значений, которые были указаны.
ИЛИ ЖЕ
Оператор OR используется для объединения нескольких условий в предложении WHERE оператора SQL.
НЕ
Оператор NOT меняет значение логического оператора, с которым он используется. Например, NOT EXISTS, NOT BETWEEN, NOT IN и т. Д. Это оператор отрицания.
SQL арифметические операторы
Ниже приведен список всех арифметических операторов, доступных в грамматике SQL DocumentDB.
S.No. | Операторы и описание |
---|---|
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»), и оно будет извлекать документ, идентификатор которого равен WakefieldFamily.
SELECT * FROM f WHERE f.id = "WakefieldFamily"
Когда вышеуказанный запрос будет выполнен, он вернет полный документ JSON для 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, "_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 используется для выражения запросов к диапазонам значений, как в SQL. МЕЖДУ можно использовать против строк или чисел. Основное различие между использованием BETWEEN в DocumentDB и ANSI SQL состоит в том, что вы можете выражать запросы диапазона по отношению к свойствам смешанных типов.
Например, в некоторых документах возможно, что у вас может быть «оценка» как число, а в других документах это могут быть строки. В этих случаях сравнение между двумя различными типами результатов является «неопределенным», и документ будет пропущен.
Давайте рассмотрим три документа из предыдущего примера. Ниже приводится документ 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 позволяет указать несколько значений в предложении WHERE. IN эквивалентно объединению нескольких предложений OR.
Сходные три документа считаются сделанными в предыдущих примерах. Ниже приводится документ 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" } ]
Давайте рассмотрим еще один простой пример, в котором будут извлечены все семейные документы, где идентификатором является «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 Tutorial».
[ "Hello World, this is DocumentDB SQL Tutorial" ]
В другом примере давайте рассмотрим три документа из предыдущих примеров.
Ниже приводится документ 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 поверх 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.
Мы еще раз рассмотрим три аналогичных документа из предыдущих примеров.
Ниже приводится документ 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 }
Давайте рассмотрим простой пример без ключевого слова IN в предложении FROM.
Ниже приведен запрос, который вернет всех родителей из коллекции 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" } ] ]
Как видно из вышеприведенного вывода, родители каждого семейства отображаются в отдельном массиве JSON.
Давайте посмотрим на тот же пример, однако на этот раз мы будем использовать ключевое слово IN в предложении FROM.
Ниже приведен запрос, содержащий ключевое слово 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 используется для объединения записей из двух или более таблиц в базе данных, и необходимость объединения разных таблиц очень важна при разработке нормализованных схем. Поскольку DocumentDB имеет дело с денормализованной моделью данных документов без схемы, JOIN в DocumentDB SQL является логическим эквивалентом «self-join».
Давайте рассмотрим три документа, как в предыдущих примерах.
Ниже приводится документ 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" } ]
В приведенном выше примере соединение происходит между корневым каталогом документа и дочерним корневым каталогом, что создает перекрестный продукт между двумя объектами JSON. Ниже приведены некоторые моменты, на которые следует обратить внимание:
-
В предложении FROM предложение JOIN является итератором.
-
Первые два документа WakefieldFamily и SmithFamily содержат двух дочерних элементов, поэтому набор результатов также содержит перекрестный продукт, который создает отдельный объект для каждого дочернего элемента.
-
Третий документ AndersenFamily содержит только одного потомка, следовательно, этому документу соответствует только один объект.
В предложении FROM предложение JOIN является итератором.
Первые два документа WakefieldFamily и SmithFamily содержат двух дочерних элементов, поэтому набор результатов также содержит перекрестный продукт, который создает отдельный объект для каждого дочернего элемента.
Третий документ AndersenFamily содержит только одного потомка, следовательно, этому документу соответствует только один объект.
Давайте посмотрим на тот же пример, однако на этот раз мы также извлекаем дочернее имя для лучшего понимания предложения 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, которое является необязательным.
Давайте рассмотрим три аналогичных документа из тех, что использовались в предыдущих примерах.
Ниже приводится документ 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
Как видно, поля city, county и state заключены в квадратные скобки, которые создадут массив, и этот массив будет называться Address. Когда вышеуказанный запрос выполняется, он производит следующий вывод.
[ { "FamilyName": "WakefieldFamily", "Address": [ "NY", "Manhattan", "NY" ] }, { "FamilyName": "SmithFamily", "Address": [ "Forest Hills", "Queens", "NY" ] }, { "FamilyName": "AndersenFamily", "Address": [ "Seattle", "King", "WA" ] } ]
Информация о городе, округе и штате добавляется в массив адресов в приведенном выше выводе.
DocumentDB SQL — Скалярные выражения
В DocumentDB SQL предложение SELECT также поддерживает скалярные выражения, такие как константы, арифметические выражения, логические выражения и т. Д. Обычно скалярные запросы используются редко, потому что на самом деле они не запрашивают документы в коллекции, они просто оценивают выражения. Но все же полезно использовать запросы скалярных выражений, чтобы изучить основы, как использовать выражения и формировать JSON в запросе, и эти концепции применяются непосредственно к фактическим запросам, которые вы будете выполнять для документов в коллекции.
Давайте посмотрим на пример, который содержит несколько скалярных запросов.
В Query Explorer выберите только текст для выполнения и нажмите «Выполнить». Давайте запустим этот первый.
SELECT "Hello"
Когда вышеуказанный запрос выполняется, он производит следующий вывод.
[ { "$1": "Hello" } ]
Этот вывод может выглядеть немного запутанным, поэтому давайте разберем его.
-
Во-первых, как мы видели в последней демонстрации, результаты запроса всегда содержатся в квадратных скобках, потому что они возвращаются в виде массива JSON, даже в результате таких запросов скалярного выражения, как этот, который возвращает только один документ.
-
У нас есть массив с одним документом, и этот документ имеет единственное свойство для одного выражения в инструкции SELECT.
-
Оператор SELECT не предоставляет имя для этого свойства, поэтому DocumentDB автоматически генерирует его, используя $ 1.
-
Обычно это не то, что нам нужно, поэтому мы можем использовать AS для создания псевдонима выражения в запросе, которое задает имя свойства в сгенерированном документе так, как вам хотелось бы, чтобы слово было в этом примере.
Во-первых, как мы видели в последней демонстрации, результаты запроса всегда содержатся в квадратных скобках, потому что они возвращаются в виде массива JSON, даже в результате таких запросов скалярного выражения, как этот, который возвращает только один документ.
У нас есть массив с одним документом, и этот документ имеет единственное свойство для одного выражения в инструкции SELECT.
Оператор 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, где в этом SqlParameterCollection определен параметр Id, назначенный свойству параметра этого SqlQuerySpec. Затем SDK выполняет работу по созданию окончательной строки запроса для DocumentDB с использованием встроенного в нее collectionId. Мы запускаем запрос и затем используем его 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
Этот запрос затем можно отправить в DocumentDB в виде параметризованного запроса JSON, как показано в следующем коде.
{ "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. | Встроенные функции и описание |
---|---|
1 | Математические функции
Математические функции выполняют вычисления, обычно основанные на входных значениях, которые предоставляются в качестве аргументов, и возвращают числовые значения. |
2 | Функции проверки типа
Функции проверки типа позволяют проверять тип выражения в запросах SQL. |
3 | Строковые функции
Строковые функции выполняют операцию над входным значением строки и возвращают строковое, числовое или логическое значение. |
4 | Функции массива
Функции массива выполняют операцию с входным значением массива и возвращают его в виде числового, логического значения или значения массива. |
5 | Пространственные функции
DocumentDB также поддерживает встроенные функции Open Geospatial Consortium (OGC) для геопространственных запросов. |
Математические функции выполняют вычисления, обычно основанные на входных значениях, которые предоставляются в качестве аргументов, и возвращают числовые значения.
Функции проверки типа позволяют проверять тип выражения в запросах SQL.
Строковые функции выполняют операцию над входным значением строки и возвращают строковое, числовое или логическое значение.
Функции массива выполняют операцию с входным значением массива и возвращают его в виде числового, логического значения или значения массива.
DocumentDB также поддерживает встроенные функции Open Geospatial Consortium (OGC) для геопространственных запросов.
DocumentDB SQL — перевод с Linq на SQL
В DocumentDB мы фактически используем SQL для запроса документов. Если мы занимаемся разработкой .NET, есть также поставщик LINQ, который можно использовать и который может генерировать соответствующий SQL из запроса LINQ.
Поддерживаемые типы данных
В DocumentDB все типы примитивов JSON поддерживаются в поставщике LINQ, включенном в DocumentDB .NET SDK, а именно:
- числовой
- логический
- строка
- Ноль
Поддерживаемое выражение
Следующие скалярные выражения поддерживаются в поставщике LINQ, входящем в состав DocumentDB .NET SDK.
-
Постоянные значения — включает постоянные значения примитивных типов данных.
-
Выражения свойства / индекса массива — выражения относятся к свойству объекта или элемента массива.
-
Арифметические выражения — включает в себя общие арифметические выражения для числовых и логических значений.
-
Выражение сравнения строк — включает сравнение строкового значения с некоторым постоянным строковым значением.
-
Выражение создания объекта / массива — возвращает объект составного типа значения или анонимного типа или массив таких объектов. Эти значения могут быть вложенными.
Постоянные значения — включает постоянные значения примитивных типов данных.
Выражения свойства / индекса массива — выражения относятся к свойству объекта или элемента массива.
Арифметические выражения — включает в себя общие арифметические выражения для числовых и логических значений.
Выражение сравнения строк — включает сравнение строкового значения с некоторым постоянным строковым значением.
Выражение создания объекта / массива — возвращает объект составного типа значения или анонимного типа или массив таких объектов. Эти значения могут быть вложенными.
Поддерживаемые операторы LINQ
Вот список поддерживаемых операторов LINQ в поставщике LINQ, включенном в DocumentDB .NET SDK.
-
Select — Проекции переводятся в SQL SELECT, включая конструкцию объекта.
-
Где — Фильтры переводят в SQL WHERE и поддерживают перевод между &&, || а также ! к операторам SQL.
-
SelectMany — позволяет разматывать массивы в предложение SQL JOIN. Может использоваться для цепочки / вложенных выражений для фильтрации элементов массива.
-
OrderBy и OrderByDescending — переводит в ORDER BY по возрастанию / убыванию.
-
CompareTo — переводит в диапазон сравнения. Обычно используется для строк, поскольку они не сопоставимы в .NET.
-
Take — переводит в SQL TOP для ограничения результатов запроса.
-
Математические функции — Поддерживает перевод из .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.
-
Определяемая пользователем функция расширения — Поддерживает перевод из метода-заглушки UserDefinedFunctionProvider.Invoke в соответствующую пользовательскую функцию.
-
Разное — Поддерживает перевод объединенных и условных операторов. Может переводить Contains в String CONTAINS, ARRAY_CONTAINS или SQL IN в зависимости от контекста.
Select — Проекции переводятся в SQL SELECT, включая конструкцию объекта.
Где — Фильтры переводят в SQL WHERE и поддерживают перевод между &&, || а также ! к операторам SQL.
SelectMany — позволяет разматывать массивы в предложение SQL JOIN. Может использоваться для цепочки / вложенных выражений для фильтрации элементов массива.
OrderBy и OrderByDescending — переводит в ORDER BY по возрастанию / убыванию.
CompareTo — переводит в диапазон сравнения. Обычно используется для строк, поскольку они не сопоставимы в .NET.
Take — переводит в SQL TOP для ограничения результатов запроса.
Математические функции — Поддерживает перевод из .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.
Определяемая пользователем функция расширения — Поддерживает перевод из метода-заглушки UserDefinedFunctionProvider.Invoke в соответствующую пользовательскую функцию.
Разное — Поддерживает перевод объединенных и условных операторов. Может переводить Contains в String CONTAINS, ARRAY_CONTAINS или SQL IN в зависимости от контекста.
Давайте посмотрим на пример, где мы будем использовать .Net SDK. Ниже приведены три документа, которые мы рассмотрим для этого примера.
Новый клиент 1
{ "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. Мы определили запрос LINQ в q , но он не будет выполняться, пока мы не запустим .ToList для него.
private static void QueryDocumentsWithLinq(DocumentClient client) { Console.WriteLine(); Console.WriteLine("**** Query Documents (LINQ) ****"); Console.WriteLine(); Console.WriteLine("Quering for US customers (LINQ)"); var q = from d in client.CreateDocumentQuery<Customer>(collection.DocumentsLink) where d.Address.CountryRegionName == "United States" select new { Id = d.Id, Name = d.Name, City = d.Address.Location.City }; var documents = q.ToList(); Console.WriteLine("Found {0} 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 в синтаксис SQL для DocumentDB, генерируя предложение SELECT и WHERE на основе нашего синтаксиса LINQ.
Давайте вызовем вышеупомянутые запросы из задачи 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 — Добавьте .NET SDK от NuGet. Мы используем .NET SDK здесь, что означает, что мы напишем некоторый код C # для создания, выполнения и удаления нашей хранимой процедуры, но сама хранимая процедура написана на JavaScript.
Шаг 3 — Щелкните правой кнопкой мыши проект в обозревателе решений.
Шаг 4. Добавьте новый файл JavaScript для хранимой процедуры и назовите его HelloWorldStoreProce.js.
Каждая хранимая процедура — это просто функция JavaScript, поэтому мы создадим новую функцию и, естественно, также назовем эту функцию HelloWorldStoreProce . Неважно, если мы дадим имя функции вообще. DocumentDB будет ссылаться на эту хранимую процедуру только по идентификатору, который мы предоставляем при ее создании.
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. Сначала создайте объект определения с идентификатором для нового ресурса, а затем вызовите один из методов Create для объекта DocumentClient . В случае хранимой процедуры определение включает в себя Id и фактический код JavaScript, который вы хотите отправить на сервер.
Шаг 7 — Вызовите File.ReadAllText, чтобы извлечь код хранимой процедуры из файла JS.
Шаг 8 — Присвойте код хранимой процедуры свойству body объекта определения.
Что касается DocumentDB, то идентификатор, который мы здесь указываем в определении, является именем хранимой процедуры, независимо от того, что мы на самом деле называем функцией JavaScript.
Тем не менее, при создании хранимых процедур и других серверных объектов рекомендуется, чтобы мы называли функции JavaScript и чтобы эти имена соответствовали идентификатору, который мы установили в определении для DocumentDB.
Шаг 9 — Вызов CreateStoredProcedureAsync , передавая SelfLink для коллекции MyCollection и определения хранимой процедуры. Это создает хранимую процедуру и ResourceId , назначенный ей DocumentDB.
Шаг 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!
Как видно из вышеприведенного вывода, свойство response имеет «Hello и добро пожаловать в DocumentDB!», Возвращаемое нашей хранимой процедурой.
DocumentDB SQL — пользовательские функции
DocumentDB SQL обеспечивает поддержку пользовательских функций (UDF). UDF — это просто еще один вид функций JavaScript, которые вы можете написать, и они работают почти так, как вы ожидаете. Вы можете создавать пользовательские функции для расширения языка запросов с помощью пользовательской бизнес-логики, на которую вы можете ссылаться в своих запросах.
SQL-синтаксис DocumentDB расширен для поддержки пользовательской логики приложения с использованием этих пользовательских функций. UDF могут быть зарегистрированы в DocumentDB, а затем на них можно ссылаться как часть запроса SQL.
Давайте рассмотрим следующие три документа для этого примера.
Документ 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 и вызываем CreateUserDefinedFunctionAsync с SelfLink коллекции и объектом udfDefinition, как показано в следующем коде.
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, передавая строку сопоставления с шаблоном во втором параметре в. совпадать Мы можем запустить запрос подстроки, чтобы найти все магазины со словом Andersen в их свойстве lastName .
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 в качестве фильтра для результирующего набора составного запроса.
Выберите параметр сокращения 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 }
Давайте посмотрим на пример каскадного запроса.
Ниже приведен запрос, который будет извлекать идентификатор и местоположение семьи, в которой первый заданный имя ребенка — Мишель.
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 — Смит.
SELECT * FROM p IN Families.parents WHERE p.familyName = "Smith"
Когда вышеуказанный запрос выполняется, он производит следующий вывод.
[ { "familyName": "Smith", "givenName": "James" } ]
Давайте рассмотрим другой пример вложенного запроса.
Ниже приведен запрос, который вернет все фамилии .
SELECT VALUE p.familyName FROM Families f JOIN p IN f.parents
Когда вышеуказанный запрос выполняется, он производит следующий вывод.