Query get: Query API — SQLAlchemy 1.4 Documentation
Query — Get (Azure Application Insights)
Выполнение аналитического запроса
Выполняет аналитический запрос данных.
With optional parameters:
GET https://api.applicationinsights.io/v1/apps/{appId}/query?query={query}×pan={timespan}
Type:
oauth3
Flow:
implicit
Authorization URL:
https://login.microsoftonline.com/common/oauth3/authorize?resource=https%3A%2F%2Fapi.applicationinsights.io
Sample Request
GET https://api.applicationinsights.io/v1/apps/34adfa4f-cedf-4dc0-ba29-b6d1a69ab345/query?query=requests | take 10×pan=PT12H
Sample Response
x-ms-request-id: 58a37988-2c05-427a-891f-5e0e1266fcc5
x-ms-correlation-request-id: 58a37988-2c05-427a-891f-5e0e1266fcc5
{
"tables": [
{
"name": "PrimaryResult",
"columns": [
{
"name": "timestamp",
"type": "datetime"
},
{
"name": "id",
"type": "string"
},
{
"name": "source",
"type": "string"
},
{
"name": "name",
"type": "string"
},
{
"name": "url",
"type": "string"
},
{
"name": "success",
"type": "string"
},
{
"name": "resultCode",
"type": "string"
},
{
"name": "duration",
"type": "real"
},
{
"name": "performanceBucket",
"type": "string"
},
{
"name": "customDimensions",
"type": "dynamic"
},
{
"name": "customMeasurements",
"type": "dynamic"
},
{
"name": "operation_Name",
"type": "string"
},
{
"name": "operation_Id",
"type": "string"
},
{
"name": "operation_ParentId",
"type": "string"
},
{
"name": "operation_SyntheticSource",
"type": "string"
},
{
"name": "session_Id",
"type": "string"
},
{
"name": "user_Id",
"type": "string"
},
{
"name": "user_AuthenticatedId",
"type": "string"
},
{
"name": "user_AccountId",
"type": "string"
},
{
"name": "application_Version",
"type": "string"
},
{
"name": "client_Type",
"type": "string"
},
{
"name": "client_Model",
"type": "string"
},
{
"name": "client_OS",
"type": "string"
},
{
"name": "client_IP",
"type": "string"
},
{
"name": "client_City",
"type": "string"
},
{
"name": "client_StateOrProvince",
"type": "string"
},
{
"name": "client_CountryOrRegion",
"type": "string"
},
{
"name": "client_Browser",
"type": "string"
},
{
"name": "cloud_RoleName",
"type": "string"
},
{
"name": "cloud_RoleInstance",
"type": "string"
},
{
"name": "appId",
"type": "string"
},
{
"name": "appName",
"type": "string"
},
{
"name": "iKey",
"type": "string"
},
{
"name": "sdkVersion",
"type": "string"
},
{
"name": "itemId",
"type": "string"
},
{
"name": "itemType",
"type": "string"
},
{
"name": "itemCount",
"type": "int"
}
],
"rows": [
[
"2018-02-01T17:33:09. 788Z",
"|0qRud6jz3k0=.c32c2659_",
null,
"GET Reports/Index",
"http://fabrikamfiberapp.azurewebsites.net/Reports",
"True",
"200",
"3.3833",
"<250ms",
"{\"_MS.ProcessedByMetricExtractors\":\"(Name:'Requests', Ver:'1.0')\"}",
null,
"GET Reports/Index",
"0qRud6jz3k0=",
"0qRud6jz3k0=",
"Application Insights Availability Monitoring",
"9fc6738d-7e26-44f0-b88e-6fae8ccb6b26",
"us-va-ash-azr_9fc6738d-7e26-44f0-b88e-6fae8ccb6b26",
null,
null,
"AutoGen_49c3aea0-4641-4675-93b5-55f7a62d22d3",
"PC",
null,
null,
"52.168.8.0",
"Boydton",
"Virginia",
"United States",
null,
"fabrikamfiberapp",
"RD00155D5053D1",
"cf58dcfd-0683-487c-bc84-048789bca8e5",
"fabrikamprod",
"5a2e4e0c-e136-4a15-9824-90ba859b0a89",
"web:2. 5.0-33031",
"051ad4ef-0776-11e8-ac6e-e30599af6943",
"request",
"1"
],
[
"2018-02-01T17:33:15.786Z",
"|x/Ysh+M1TfU=.c32c265a_",
null,
"GET Home/Index",
"http://fabrikamfiberapp.azurewebsites.net/",
"True",
"200",
"716.2912",
"500ms-1sec",
"{\"_MS.ProcessedByMetricExtractors\":\"(Name:'Requests', Ver:'1.0')\"}",
null,
"GET Home/Index",
"x/Ysh+M1TfU=",
"x/Ysh+M1TfU=",
"Application Insights Availability Monitoring",
"58b15be6-d1e6-4d89-9919-52f63b840913",
"emea-se-sto-edge_58b15be6-d1e6-4d89-9919-52f63b840913",
null,
null,
"AutoGen_49c3aea0-4641-4675-93b5-55f7a62d22d3",
"PC",
null,
null,
"51.141.32.0",
"Cardiff",
"Cardiff",
"United Kingdom",
null,
"fabrikamfiberapp",
"RD00155D5053D1",
"cf58dcfd-0683-487c-bc84-048789bca8e5",
"fabrikamprod",
"5a2e4e0c-e136-4a15-9824-90ba859b0a89",
"web:2. 5.0-33031",
"051ad4f0-0776-11e8-ac6e-e30599af6943",
"request",
"1"
]
]
}
]
}
Столбец таблицы.
Сведения об ошибке.
Код и сообщение об ошибке.
Сведения об ошибке.
Ответ на запрос.
Таблица ответов на запрос.
Query — Get (Azure Log Analytics)
Выполнение аналитического запроса
Выполняет аналитический запрос данных.
В этой статье
GET https://api.loganalytics.io/v1/workspaces/{workspaceId}/query?query={query}
With optional parameters:
GET https://api.loganalytics.io/v1/workspaces/{workspaceId}/query?query={query}×pan={timespan}
Параметры URI
Name | In | Required | Type | Description |
---|---|---|---|---|
workspace | path | True | ИДЕНТИФИКАТОР рабочей области. Это идентификатор рабочей области из колонки свойств в портал Azure. | |
query | query | True | Аналитический запрос. Дополнительные сведения о синтаксисе запросов аналитики | |
timespan | query | duration | Необязательный параметр. Интервал времени, на который запрашиваются данные. Это значение периода времени ISO8601. Этот интервал времени применяется в дополнение к любым, указанным в выражении запроса. |
Ответы
Name | Type | Description |
---|---|---|
200 OK | Все в порядке. Вызов API завершился, и результат запроса аналитики находится в полезных данных ответа | |
Other Status Codes | Объект ответа об ошибке. |
Безопасность
azure_auth
Поток OAuth3 Azure Active Directory
Type:
oauth3
Flow:
implicit
Authorization URL:
https://login.microsoftonline.com/common/oauth3/authorize
Scopes
Name | Description |
---|---|
user_impersonation | олицетворение учетной записи пользователя |
Примеры
cross-workspace
Sample Request
GET https://api.loganalytics.io/v1/workspaces/63613592-b6f7-4c3d-a390-22ba13102111/query?query=union * | where TimeGenerated > ago(1h) | summarize count() by Type, TenantId
Sample Response
{
"tables": [
{
"name": "PrimaryResult",
"columns": [
{
"name": "Type",
"type": "string"
},
{
"name": "TenantId",
"type": "string"
},
{
"name": "count_",
"type": "long"
}
],
"rows": [
[
"Usage",
"63613592-b6f7-4c3d-a390-22ba13102111",
"1"
],
[
"Usage",
"d436f322-a9f4-4aad-9a7d-271fbf66001c",
"1"
],
[
"BillingFact",
"63613592-b6f7-4c3d-a390-22ba13102111",
"1"
],
[
"BillingFact",
"d436f322-a9f4-4aad-9a7d-271fbf66001c",
"1"
],
[
"Operation",
"63613592-b6f7-4c3d-a390-22ba13102111",
"7"
],
[
"Operation",
"d436f322-a9f4-4aad-9a7d-271fbf66001c",
"5"
]
]
}
]
}
simple-query
Sample Request
GET https://api. loganalytics.io/v1/workspaces/63613592-b6f7-4c3d-a390-22ba13102111/query?query=Usage | take 10×pan=PT12H
Sample Response
x-ms-request-id: 58a37988-2c05-427a-891f-5e0e1266fcc5
x-ms-correlation-request-id: 58a37988-2c05-427a-891f-5e0e1266fcc5
{
"tables": [
{
"name": "PrimaryResult",
"columns": [
{
"name": "TenantId",
"type": "string"
},
{
"name": "Computer",
"type": "string"
},
{
"name": "TimeGenerated",
"type": "datetime"
},
{
"name": "SourceSystem",
"type": "string"
},
{
"name": "StartTime",
"type": "datetime"
},
{
"name": "EndTime",
"type": "datetime"
},
{
"name": "ResourceUri",
"type": "string"
},
{
"name": "LinkedResourceUri",
"type": "string"
},
{
"name": "DataType",
"type": "string"
},
{
"name": "Solution",
"type": "string"
},
{
"name": "BatchesWithinSla",
"type": "long"
},
{
"name": "BatchesOutsideSla",
"type": "long"
},
{
"name": "BatchesCapped",
"type": "long"
},
{
"name": "TotalBatches",
"type": "long"
},
{
"name": "AvgLatencyInSeconds",
"type": "real"
},
{
"name": "Quantity",
"type": "real"
},
{
"name": "QuantityUnit",
"type": "string"
},
{
"name": "IsBillable",
"type": "bool"
},
{
"name": "MeterId",
"type": "string"
},
{
"name": "LinkedMeterId",
"type": "string"
},
{
"name": "Type",
"type": "string"
}
],
"rows": [
[
"b438b4f6-912a-46d5-9cb1-b44069212abc",
"ContosoSQLSrv1",
"2017-08-24T06:59:59Z",
"OMS",
"2017-08-24T06:00:00Z",
"2017-08-24T06:59:59Z",
"/subscriptions/e4272367-5645-4c4e-9c67-3b74b59a6982/resourcegroups/contosoazurehq/providers/microsoft. operationalinsights/workspaces/contosoretail-it",
null,
"Perf",
"LogManagement",
"1",
"0",
"0",
"1",
"1.286",
"0.076408",
"MBytes",
"true",
"a4e29a95-5b4c-408b-80e3-113f9410566e",
"00000000-0000-0000-0000-000000000000",
"Usage"
],
[
"b438b4f6-912a-46d5-9cb1-b44069212abc",
"Store010Web3",
"2017-08-24T06:59:59Z",
"OMS",
"2017-08-24T06:00:00Z",
"2017-08-24T06:59:59Z",
"/subscriptions/e4272367-5645-4c4e-9c67-3b74b59a6982/resourcegroups/contosoazurehq/providers/microsoft.operationalinsights/workspaces/contosoretail-it",
null,
"Perf",
"LogManagement",
"1",
"0",
"0",
"1",
"1.7",
"0.106767",
"MBytes",
"true",
"a4e29a95-5b4c-408b-80e3-113f9410566e",
"00000000-0000-0000-0000-000000000000",
"Usage"
]
]
}
]
}
Определения
column | Столбец таблицы. |
error | Сведения об ошибке. |
error | Код и сообщение об ошибке. |
error | Сведения об ошибке. |
query | Ответ на запрос. |
table | Таблица ответов на запрос. |
column
Столбец таблицы.
Name | Type | Description |
---|---|---|
name | Имя этого столбца. | |
type | Тип данных этого столбца. |
errorDetail
Сведения об ошибке.
Name | Type | Description |
---|---|---|
additionalProperties | Дополнительные свойства, которые можно указать в объекте сведений об ошибке | |
code | Код ошибки. | |
message | Сообщение об ошибке, читаемое человеком. | |
resources | Указывает ресурсы, которые были ответственны за ошибку. | |
target | Указывает, какое свойство в запросе отвечает за ошибку. | |
value | Указывает, какое значение в «Target» отвечает за ошибку. |
errorInfo
Код и сообщение об ошибке.
Name | Type | Description |
---|---|---|
additionalProperties | Дополнительные свойства, которые могут быть предоставлены объекту сведений об ошибке | |
code | Код ошибки, доступной для чтения компьютера. | |
details | сведения об ошибке. | |
innererror | Код и сообщение об ошибке. | |
message | Сообщение об ошибке, читаемое человеком. |
errorResponse
Сведения об ошибке.
Name | Type | Description |
---|---|---|
error | Код и сообщение об ошибке. |
queryResults
Ответ на запрос.
Name | Type | Description |
---|---|---|
tables | Список таблиц, столбцов и строк. |
table
Таблица ответов на запрос.
Name | Type | Description |
---|---|---|
columns | Список столбцов в этой таблице. | |
name | Имя таблицы. | |
rows | Результирующие строки из этого запроса. |
Другие результаты | |
For more info, see Get started with queries or Create a simple select query. | Дополнительные сведения см. в статье Начало работы с запросами или Создание простого запроса на выборку. |
On the first page of the Lookup Wizard, select I want the lookup field to get values from another table or query. | На первой странице мастера подстановок выберите Получать значения из другой таблицы или запроса для поля подстановки. |
To understand which data you’ll get from your query, read the text carefully in the Join Properties dialog box. | Чтобы понять, какие данные будут выводиться при помощи запроса, внимательно прочитайте текст в диалоговом окне Параметры объединения. |
Note: While running a query that returns a large amount of data you might get an error message indicating that you will not be able to undo the query. | Примечание: При выполнении запроса, который возвращает большое количество данных, может появится сообщение об ошибке, в котором будет сказано, что отменить запрос не удастся. |
I was surprised to get your query. | Меня удивил ваш запрос. |
Well, you tell that sumbitch, he thinks he’s gonna come over here and get my recipes… well, I got a double-barreled answer to his query right inside. | Передайте этой мрази, что если он думает украсть мои рецепты,.. …то я на его хитрости дам двуствольный ответ. |
Get on with your reading, you lazy clown! he said querulously, rubbing his eyes just as if he had been awakened from sleep. | А ты читай, ленивый мужик! — ворчливо говорил он, точно проснувшись, протирая пальцами глаза. |
What did Jamieson get out of it? was the query. | И у всех, естественно, возник вопрос: — Любопытно, сколько заработал на этом Джемисон? |
How do I get one search query to automatically redirect to another? | Таким образом, кислород восстанавливается до воды, а исходные акцепторы электронов NAD+ и хинон регенерируются. |
Users can leave the search bar empty to see all pages within an area or type a query to get subject specific information. | Пользователи могут оставить строку поиска пустой, чтобы просмотреть все страницы в пределах области, или ввести запрос, чтобы получить конкретную информацию о предмете. |
In contrast to SOAP, JSON-RPC is overly simplistic and basically tunnels HTTP GET-style key/value pairs within a query string using JSON. | В отличие от SOAP, JSON-RPC чрезмерно упрощен и в основном туннелирует пары ключ/значение в стиле HTTP GET внутри строки запроса с помощью JSON. |
API запросов
— Документация по SQLAlchemy 1.4
Создайте SQL JOIN для этого запроса
критерий объекта
и применять генеративно, возвращая вновь полученный
Запрос
.
Простое соединение отношений
Рассмотрим сопоставление между двумя классами Пользователь
и Адрес
,
с отношением User. addresses
, представляющим коллекцию
из Адрес
объектов, связанных с каждым пользователем
.Большинство
общее использование Query.join ()
заключается в создании СОЕДИНЕНИЯ на этом
отношения, используя атрибут User.addresses
в качестве индикатора
как это должно происходить:
q = session.query (Пользователь) .join (User.addresses)
Где указано выше, вызов Query.join ()
по
User.addresses
приведет к SQL, приблизительно эквивалентному:
ВЫБЕРИТЕ user.id, user.name FROM user JOIN address ON user.id = address.user_id
В приведенном выше примере мы обращаемся к пользователю .адреса
, как передано
Query.join ()
как «предложение on», то есть указывает
как должна быть построена «ON» часть JOIN.
Чтобы построить цепочку объединений, несколько Query.join ()
звонки могут быть использованы. Атрибут, связанный с отношениями, подразумевает как
левая и правая сторона соединения одновременно:
q = session. query (Пользователь). \ присоединиться (User.orders). \ присоединиться (Order.items). \ присоединиться (Item.keywords)
Примечание
, как показано в приведенном выше примере, порядок, в котором каждый
вызов метода join () имеет значение .Запрос не будет,
например, знать, как правильно присоединиться, если мы укажем
Пользователь
, затем Элемент
, затем Заказ
в нашей цепочке объединений; в
такой случай, в зависимости от переданных аргументов, может вызвать
ошибка, связанная с тем, что он не знает, как присоединиться, или может привести к недопустимому
SQL, и в этом случае база данных вызовет ошибку. В правильном
практика,
Query.join () Метод
вызывается таким образом, что строки
как мы хотели бы, чтобы предложения JOIN в SQL были
визуализирован, и каждый вызов должен представлять собой четкую ссылку, откуда
предшествует этому.
Присоединяется к целевому объекту или выбирается
Вторая форма Query. join ()
позволяет любому отображаемому объекту или
основная выбираемая конструкция в качестве цели. В этом использовании
Query.join ()
попытается создать JOIN по
естественные отношения внешнего ключа между двумя объектами:
q = session.query (Пользователь) .join (Адрес)
В приведенной выше форме вызова Query.join ()
вызывается для
автоматически создайте для нас «предложение о включении».Эта форма вызова будет
в конечном итоге вызывает ошибку, если между ними нет внешних ключей
два объекта, или если между ними существует несколько связей внешнего ключа
целевой объект и объект или объекты, уже присутствующие на
слева, так что для создания соединения требуется дополнительная информация. Примечание
что при указании соединения с целью без какого-либо предложения ON ORM
настроенные отношения не принимаются во внимание.
Присоединяется к цели с предложением ON
Третья форма вызова позволяет как целевой объект, так и
как предложение ON, которое необходимо передать явно. Пример, который включает
выражение SQL в качестве предложения ON выглядит следующим образом:
q = session.query (Пользователь) .join (Адрес, User.id == Address.user_id)
Приведенная выше форма может также использовать атрибут, связанный с отношениями, в качестве
Предложение ON:
q = session.query (Пользователь) .join (Адрес, User.addresses)
Приведенный выше синтаксис может быть полезен в том случае, если мы хотим
для присоединения к псевдониму конкретной целевой сущности. Если бы мы хотели
чтобы присоединиться к Адресу
дважды, это может быть достигнуто с помощью двух
псевдонимы, настроенные с помощью функции aliased ()
:
a1 = псевдоним (адрес) a2 = псевдоним (адрес) q = сеанс.запрос (Пользователь). \ join (a1, User.addresses). \ join (a2, User.addresses). \ фильтр (a1.email_address == '[email protected]'). \ фильтр (a2.email_address == '[email protected]')
Форма вызова, связанная с отношениями, также может указывать целевую сущность
с использованием метода PropComparator. of_type ()
; запрос
эквивалент приведенному выше:
a1 = псевдоним (адрес) a2 = псевдоним (адрес) q = session.query (Пользователь). \ присоединиться (User.addresses.of_type (a1)). \ присоединиться (User.address.of_type (a2)). \ фильтр (a1.email_address == '[email protected]'). \ фильтр (a2.email_address == '[email protected]')
Дополнение встроенных предложений ON
В качестве замены для обеспечения полного настраиваемого состояния включения для
существующие отношения, функция PropComparator.and_ ()
может применяться к атрибуту отношения для увеличения дополнительных
критерии в предложение ON; дополнительные критерии будут объединены
с критериями по умолчанию с использованием AND:
q = сеанс.запрос (Пользователь) .join ( User.addresses.and_ (Address.email_address! = '[email protected]') )
Присоединение к таблицам и подзапросам
Целью соединения также может быть любая таблица или оператор SELECT,
которые могут быть связаны с целевой организацией или нет. Использовать
соответствующий метод .subquery ()
, чтобы сделать подзапрос
вне запроса:
subq = session.query (Адрес). \ фильтр (Address.email_address == '[email protected]'). \ подзапрос () q = session.query (Пользователь).присоединиться( subq, User.id == subq.c.user_id )
Присоединение к подзапросу с точки зрения определенной связи и / или
целевая сущность может быть достигнута путем связывания подзапроса с
объект, использующий aliased ()
:
subq = session.query (Адрес). \ фильтр (Address.email_address == '[email protected]'). \ подзапрос () address_subq = псевдоним (Адрес, subq) q = session.query (Пользователь) .join ( User.addresses.of_type (address_subq) )
Контроль, к чему присоединяться из
В тех случаях, когда в левой части текущего состояния
Запрос
не соответствует тому, из чего мы хотим присоединиться,
Запрос .select_from ()
может использоваться метод:
q = session. query (Адрес) .select_from (Пользователь). \ присоединиться (User.addresses). \ фильтр (User.name == 'ed')
, который будет производить SQL, аналогичный:
ВЫБРАТЬ адрес. * ОТ пользователя ПРИСОЕДИНЯЙТЕСЬ адрес НА user.id = address.user_id ГДЕ user.name =: name_1
Устаревшие функции Query.join ()
Не рекомендуется, начиная с версии 1.4: Следующие функции устарели и будут
быть удаленным в SQLAlchemy 2.0.
Метод Query.join ()
в настоящее время поддерживает несколько
шаблоны использования и аргументы, которые считаются устаревшими
с SQLAlchemy 1.3. Путь прекращения поддержки будет следовать
в серии 1.4 для следующих функций:
Объединение по именам отношений, а не по атрибутам:
session.query (Пользователь) .join ("адреса")
Почему это устаревшая версия : имя строки не обеспечивает достаточного контекста
дляQuery. join ()
, чтобы всегда знать, что нужно,
особенно в том, что нет никаких указаний на то, что левая сторона
соединения должно быть.Это приводит к появлению таких флагов, как
from_joinpoint
, а также возможность разместить несколько
предложения join в одном вызовеQuery.join ()
которые не решают проблему полностью, но
добавление новых стилей вызова, которые не нужны и дорого обходятся
приспособиться внутренне.Современный образец звонка : используйте фактическую связь,
напримерАдрес пользователя
в приведенном выше случае:session.query (Пользователь) .join (User.addresses)
Автоматический псевдоним с
aliased = True
flag:сессия.query (Node) .join (Node.children, aliased = True). \ фильтр (Node.name == 'какое-то имя')
Почему это устаревшая модель : функция автоматического псевдонима
Запрос
очень сложен, как в своей внутренней
реализации, а также в его наблюдаемом поведении, и почти
никогда не использовался. При осмотре трудно узнать, где и когда
его псевдоним целевой сущности,Узел
в приведенном выше случае, будет
применяется, а когда не будет, и, кроме того, функция должна использовать
очень сложная эвристика для достижения такого неявного поведения.Современный шаблон вызова : используйте конструкцию
aliased ()
явно:из sqlalchemy.orm import aliased n1 = с псевдонимом (узел) session.query (Node) .join (Node.children.of_type (n1)). \ filter (n1.name == 'какое-то имя')
Несколько подключений за один звонок:
session.query (Пользователь) .join ("заказы", "предметы") session.query (Пользователь) .join (User.orders, Order.items) session.query (Пользователь) .join ( (Заказ, Пользователь. Заказы), (Позиция, позиция.order_id == Order.id) ) # ... и еще несколько форм собственно
Почему это унаследованное : возможность объединить несколько предложений ON в одно
вызовQuery. join ()
— еще одна попытка решить
проблема с возможностью указать, к какому объекту присоединиться,
и является источником большого разнообразия потенциальных моделей вызова
которые изнутри дороги и сложны для анализа и
приспособиться.Современный шаблон вызова : использовать атрибуты, связанные с отношениями
или SQL-ориентированные предложения ON в отдельных вызовах, так что
каждый звонок наQuery.join ()
знает, что осталось
сторона должна быть:session.query (Пользователь) .join (User.orders) .join ( Товар, Item.order_id == Order.id)
- Параметры
* props — Входящие аргументы для
Query.join ()
,
коллекцию реквизита в современном использовании следует рассматривать как единую
или форма с двумя аргументами, как единая «целевая» сущность или ORM
связь с атрибутом, или как целевая сущность плюс
предложение », которое может быть выражением SQL или привязанным к атрибуту ORM
отношение.isouter = False — Если True, используемое соединение будет левым внешним соединением,
точно так же, как если бы был вызван методQuery.outerjoin ()
.full = False —
render FULL OUTER JOIN; подразумевает
isouter
.from_joinpoint = False —
При использовании
aliased = True
параметр
of True приведет к тому, что соединение будет из самого последнего
присоединилась к цели, вместо того, чтобы начинать с исходной
FROM предложения запроса.Примечание
Этот флаг считается устаревшим.
aliased = False —
Если True, укажите, что цель JOIN должна быть
анонимно с псевдонимом. Последующие вызовыQuery.filter ()
и подобное адаптирует входящий критерий к цели
псевдоним, пока не будет вызванQuery.reset_joinpoint ()
.Примечание
Этот флаг считается устаревшим.
Select, Insert, Delete — Документация Flask-SQLAlchemy (2.х)
Теперь, когда вы объявили модели, пора запросить
данные из базы данных. Мы будем использовать определения модели из
Глава Quickstart.
Вставка записей
Прежде чем мы сможем запросить что-то, нам нужно будет вставить некоторые данные. Все твои
у моделей должен быть конструктор, поэтому обязательно добавьте его, если вы забыли.
Конструкторы используются только вами, а не внутри SQLAlchemy, поэтому
полностью зависит от вас, как вы их определяете.
Вставка данных в базу данных состоит из трех этапов:
Создайте объект Python
Добавить в сеанс
Подтвердить сеанс
Это не сеанс Flask, а сеанс Flask-SQLAlchemy.По сути, это усиленная версия транзакции базы данных. Это
как это работает:
>>> из yourapp import User >>> me = Пользователь ('admin', '[email protected]') >>> db. session.add (я) >>> db.session.commit ()
Хорошо, это было несложно. Что происходит в какой момент? Прежде чем добавить
объект в сеанс, SQLAlchemy в принципе не планирует его добавлять
к сделке. Это хорошо, потому что вы все еще можете выбросить
изменения. Например, подумайте о создании публикации на странице, но вы только
хотите передать сообщение в шаблон для предварительного просмотра вместо
сохраняя его в базе данных.
Затем вызов функции add ()
добавляет
предмет. Он выдаст инструкцию INSERT для базы данных, но
поскольку транзакция все еще не совершена, вы не получите обратно идентификатор
немедленно. Если вы сделаете коммит, у вашего пользователя будет ID:
.
Удаление записей
Удаление записей очень похоже, вместо
добавить ()
использовать
удалить ()
:
>>> db.session.delete (я) >>> db.session.commit ()
Запросы к записям
Так как же нам получить данные из нашей базы данных? Для этого
Flask-SQLAlchemy предоставляет атрибут запроса
на вашем
Модель
класс. Когда вы получите к нему доступ, вы получите новый запрос
объект по всем записям. Затем вы можете использовать такие методы, как
filter ()
для фильтрации записей перед
вы запускаете select с all ()
или
первый ()
. Если вы хотите пройти мимо
первичный ключ, вы также можете использовать get ()
.
Следующие запросы предполагают следующие записи в базе данных:
Получить пользователя по имени пользователя:
>>> peter = User.query.filter_by (username = 'peter'). First () >>> питер.я бы 2 >>> peter.email u'[email protected] '
То же, что и выше, но для несуществующего имени пользователя дает Нет :
>>> missing = User.query.filter_by (username = 'missing'). First () >>> отсутствует Нет Истинный
Выбор группы пользователей по более сложному выражению:
>>> User.query.filter (User.email.endswith ('@ example.com')). All () [<Пользователь u'admin '>, <Пользователь u'guest'>]
Упорядочивание пользователей по чему-то:
>>> Пользователь. query.order_by (User.username) .all () [<Пользователь u'admin '>, <Пользователь u'guest'>, <Пользователь u'peter '>]
Ограничение пользователей:
>>> User.query.limit (1) .all () [<Пользователь u'admin '>]
Получение пользователя по первичному ключу:
>>> User.query.get (1) <Пользователь u'admin '>
запросов в просмотрах
Если вы пишете функцию просмотра Flask, часто бывает очень удобно вернуть 404
ошибка отсутствия записей. Поскольку это очень распространенная идиома,
Flask-SQLAlchemy предоставляет помощника именно для этой цели.Вместо
get ()
можно использовать
get_or_404 ()
и вместо
первый ()
первый_или_404 ()
.
Это вызовет ошибку 404 вместо возврата Нет :
@ app.route ('/ user / <имя пользователя>') def show_user (имя пользователя): user = User.query.filter_by (имя пользователя = имя пользователя) .first_or_404 () return render_template ('show_user. html', пользователь = пользователь)
Кроме того, если вы хотите добавить описание с помощью abort (), вы также можете использовать его как аргумент.
>>> User.query.filter_by (username = username) .first_or_404 (description = 'Нет данных с {}'. Format (username))
Выполнение запросов | Документация Django
После создания моделей данных Django
автоматически предоставляет вам API абстракции базы данных, который позволяет вам создавать,
получать, обновлять и удалять объекты. В этом документе объясняется, как использовать это
API. Обратитесь к справке по модели данных для полной
подробные сведения обо всех различных вариантах поиска модели.
В этом руководстве (и в справочной информации) мы будем ссылаться на следующие
моделей, составляющих приложение для веб-журнала:
Создание объектов¶
Для представления данных таблицы базы данных в объектах Python Django использует интуитивно понятный
система: класс модели представляет таблицу базы данных, и ее экземпляр
class представляет конкретную запись в таблице базы данных.
Чтобы создать объект, создайте его экземпляр, используя аргументы ключевого слова для класса модели,
затем вызовите save ()
, чтобы сохранить его в базе данных.
Предполагая, что модели находятся в файле mysite / blog / models.py
, вот пример:
>>> из blog.models import Blog >>> b = Блог (name = 'Beatles Blog', tagline = 'Все последние новости Beatles.') >>> b.save ()
За кулисами выполняет оператор SQL INSERT
.Джанго не попадает
базу данных, пока вы явно не вызовете save ()
.
Метод save ()
не имеет возвращаемого значения.
См. Также
save ()
принимает ряд дополнительных параметров, не
описано здесь. Документацию для
save ()
для получения полной информации.
Чтобы создать и сохранить объект за один шаг, используйте
create ()
метод.
Сохранение изменений в объектах¶
Чтобы сохранить изменения в объекте, который уже находится в базе данных, используйте
сохранить ()
.
Учитывая экземпляр Blog
b5
, который уже был сохранен в базе данных,
в этом примере изменяется его имя и обновляется запись в базе данных:
>>> b5.name = 'Новое имя' >>> b5.save ()
Это выполняет оператор SQL UPDATE
за кулисами. Джанго не попадает
базу данных, пока вы явно не вызовете save ()
.
Сохранение
полей ForeignKey
и ManyToManyField
¶
Обновление поля ForeignKey
работает точно так же
как сохранить обычное поле — присвоить полю объект нужного типа
обсуждаемый.В этом примере обновляется атрибут blog
записи Entry
экземпляр , запись
, при условии, что соответствующие экземпляры , запись
и , блог
.
уже сохранены в базе данных (поэтому мы можем получить их ниже):
>>> из blog.models import Blog, Entry >>> entry = Entry.objects.get (pk = 1) >>> cheese_blog = Blog. objects.get (name = "Разговор о Чеддере") >>> entry.blog = сырный_блог >>> entry.save ()
Обновление ManyToManyField
немного работает
иначе — используйте
add ()
метод на поле
чтобы добавить запись в отношение.В этом примере добавлен экземпляр Author
джо
до запись
объект:
>>> from blog.models import Author >>> joe = Author.objects.create (name = "Джо") >>> entry.authors.add (Джо)
Чтобы добавить несколько записей в ManyToManyField
в одном
go, включите несколько аргументов в вызов
добавить ()
, вот так:
>>> john = Author.objects.create (name = "John") >>> paul = Автор.objects.create (name = "Пол") >>> george = Author.objects.create (name = "Джордж") >>> ringo = Author.objects.create (name = "Ringo") >>> entry.authors.add (джон, пол, джордж, ринго)
Django будет жаловаться, если вы попытаетесь назначить или добавить объект неправильного типа.
Получение объектов¶
Чтобы получить объекты из базы данных, создайте
QuerySet
через
Manager
на свой модельный класс.
QuerySet
представляет собой набор объектов.
из вашей базы данных.Он может иметь ноль, один или несколько фильтров . Фильтры узкие
вниз результаты запроса на основе заданных параметров. В терминах SQL
QuerySet
соответствует оператору SELECT
,
а фильтр — это ограничивающее предложение, такое как WHERE
или LIMIT
.
Вы получаете QuerySet
, используя
Менеджер
. В каждой модели есть как минимум один
Менеджер
, и он называется
объектов
по умолчанию. Доступ к нему напрямую через
класс модели, например:
>>> Блог.объекты <объект django.db.models.manager.Manager в ...> >>> b = Блог (name = 'Foo', tagline = 'Bar') >>> б.объекты Проследить: ... AttributeError: «Менеджер недоступен через экземпляры блога».
Примечание
Менеджеры
доступны только через классы модели, а не из модели
экземпляров, чтобы обеспечить разделение между операциями «уровня таблицы» и
Операции «рекордного уровня».
Manager
является основным источником QuerySets
для
модель.Например, Blog.objects.all ()
возвращает
QuerySet
, который содержит все Blog
объектов в
база данных.
Получение всех объектов¶
Самый простой способ получить объекты из таблицы — получить их все. Сделать
для этого используйте метод all ()
на
Менеджер
:
>>> all_entries = Entry.objects.all ()
Метод all ()
возвращает
QuerySet
всех объектов в базе данных.
Получение определенных объектов с помощью фильтров¶
QuerySet
, возвращенный
all ()
описывает все объекты в
таблица базы данных. Однако обычно вам нужно выбрать только часть
полный набор предметов.
Чтобы создать такое подмножество, вы уточняете начальный
QuerySet
, добавление условий фильтрации. Два
наиболее распространенные способы уточнения QuerySet
:
-
фильтр (** kwargs)
- Возвращает новый
QuerySet
, содержащий объекты
которые соответствуют заданным параметрам поиска. -
исключить (** kwargs)
- Возвращает новый
QuerySet
, содержащий объекты
которые не соответствуют заданным параметрам поиска.
Параметры поиска ( ** kwargs
в определениях функций выше) должны
быть в формате, описанном в разделе «Поиск полей» ниже.
Например, чтобы получить QuerySet
записей блога
с 2006 года используйте фильтр ()
как
итак:
Entry.objects.filter (pub_date__year = 2006)
С классом менеджера по умолчанию он такой же, как:
Въезд. objects.all (). filter (pub_date__year = 2006)
Объединение фильтров¶
Результат уточнения QuerySet
сам по себе
QuerySet
, поэтому можно связать
уточнения вместе. Например:
>>> Entry.objects.filter ( ... headline__startswith = 'Что' ... ).исключать( ... pub_date__gte = datetime.date.today () ...) .filter ( ... pub_date__gte = datetime.date (2005, 1, 30) ...)
Требуется начальный QuerySet
всех записей
в базе данных добавляет фильтр, затем исключение, затем еще один фильтр.В
окончательный результат — QuerySet
, содержащий все
записи с заголовком, начинающимся с «Что», опубликованные между
30 января 2005 года и текущий день.
Отфильтровано
QuerySet
уникальных ¶
Каждый раз, когда вы уточняете QuerySet
, вы получаете
совершенно новый QuerySet
, который никоим образом не связан с
предыдущий QuerySet
. Каждое усовершенствование создает
отдельный и отличный QuerySet
, который может быть
хранятся, используются и используются повторно.
Пример:
>>> q1 = Entry.objects.filter (headline__startswith = "What") >>> q2 = q1.exclude (pub_date__gte = datetime.date.today ()) >>> q3 = q1.filter (pub_date__gte = datetime.date.today ())
Эти три набора QuerySets
являются отдельными. Первый — это база
QuerySet
, содержащий все записи, содержащие
заголовок, начинающийся с «Что». Второй — подмножество первого, с
дополнительные критерии, исключающие записи, pub_date которых
сегодня или в
будущее.Третий — подмножество первого, с дополнительными критериями, которые
выбирает только записи, у которых pub_date
сегодня или в будущем. В
исходный QuerySet
( q1
) не зависит от
процесс доработки.
QuerySet
ленивые¶
QuerySets
ленивы — процесс создания
QuerySet
не использует базу данных
Мероприятия. Вы можете складывать фильтры вместе целый день, и Django не
фактически запускайте запрос, пока QuerySet
не будет
оценили . Взгляните на этот пример:
>>> q = Entry.objects.filter (headline__startswith = "What") >>> q = q.filter (pub_date__lte = datetime.date.today ()) >>> q = q.exclude (body_text__icontains = "еда") >>> print (q)
Хотя это выглядит как три попадания в базу данных, на самом деле он попадает только в базу данных
один раз, в последней строке ( print (q)
). В целом результаты
QuerySet
не извлекаются из базы данных
пока вы не «попросите» их.Когда вы это сделаете,
QuerySet
— это , оцененный путем доступа к
база данных. Для получения более подробной информации о точном времени проведения оценки см.
Когда QuerySets оцениваются.
Получение одного объекта с помощью
get ()
¶
filter ()
всегда даст вам
QuerySet
, даже если соответствует только один объект
запрос — в данном случае это будет
QuerySet
, содержащий единственный элемент.
Если вы знаете, что существует только один объект, соответствующий вашему запросу, вы можете использовать
get ()
метод на
Менеджер
, который возвращает объект напрямую:
>>> one_entry = Запись. objects.get (pk = 1)
Вы можете использовать любое выражение запроса с
get ()
, как и с
filter ()
— снова см. Поиск полей
ниже.
Обратите внимание, что есть разница между использованием
get ()
и используя
фильтр ()
со срезом [0]
. Если
нет результатов, соответствующих запросу,
get ()
вызовет DoesNotExist
исключение. Это исключение является атрибутом класса модели, к которому относится запрос.
выполняется — так в коде выше, если нет объекта Entry
с
если первичный ключ равен 1, Django вызовет Entry.Не существует
.
Точно так же Django будет жаловаться, если более одного элемента соответствует
get ()
запрос. В этом случае он поднимет
MultipleObjectsReturned
, который снова является
атрибут самого класса модели.
Ограничение
QuerySet
s¶
Используйте подмножество синтаксиса разделения массива Python, чтобы ограничить
QuerySet
на определенное количество результатов. Этот
является эквивалентом предложений SQL LIMIT
и OFFSET
.
Например, это возвращает первые 5 объектов ( LIMIT 5
):
>>> Entry.objects.all () [: 5]
Возвращает объекты с шестого по десятый ( OFFSET 5 LIMIT 5
):
>>> Entry.objects.all () [5:10]
Отрицательная индексация (например, Entry.objects.all () [- 1]
) не поддерживается.
Как правило, нарезка QuerySet
возвращает новый
QuerySet
— не оценивает запрос.An
Исключение составляют случаи, когда вы используете параметр «шаг» синтаксиса фрагмента Python. За
Например, это фактически выполнит запрос, чтобы вернуть список
каждые секунда объект первого 10:
>>> Entry.objects.all () [: 10: 2]
Дальнейшая фильтрация или упорядочение срезанного набора запросов запрещены из-за
неоднозначный характер того, как это могло бы работать.
Для получения одного объекта , а не списка
(например, SELECT foo FROM bar LIMIT 1
) используйте индекс вместо фрагмента. За
Например, это возвращает первую запись
в базе данных после заказа
записей в алфавитном порядке по заголовкам:
>>> Entry.objects.order_by ('заголовок') [0]
Это примерно эквивалентно:
>>> Entry.objects.order_by ('заголовок') [0: 1] .get ()
Обратите внимание, однако, что первый из них вызовет IndexError
, в то время как
второй вызовет DoesNotExist
, если ни один объект не соответствует заданным критериям. Видеть
get ()
для получения более подробной информации.
Поиск полей¶
Поиск по полю — это то, как вы указываете основную часть предложения SQL WHERE
. Они
указаны как аргументы ключевого слова для QuerySet
методы filter ()
,
исключить ()
и
получить ()
.
Аргументы ключевого слова базового поиска имеют вид field__lookuptype = значение
.
(Это двойное подчеркивание). Например:
>>> Entry.objects.filter (pub_date__lte = '2006-01-01')
переводится (примерно) в следующий SQL:
ВЫБРАТЬ * FROM blog_entry WHERE pub_date <= '2006-01-01';
Как это возможно
Python имеет возможность определять функции, которые принимают произвольное имя-значение
аргументы, имена и значения которых оцениваются во время выполнения.Для большего
информацию см. в разделе «Аргументы ключевых слов» в официальном руководстве по Python.
Поле, указанное в поиске, должно быть именем поля модели. Есть
за одним исключением: в случае ForeignKey
вы
можно указать имя поля с суффиксом _id
. В этом случае значение
ожидается, что параметр будет содержать исходное значение первичной
ключ. Например:
>>> Entry.objects.filter (blog_id = 4)
Если вы передадите недопустимый аргумент ключевого слова, функция поиска вызовет
Ошибка типа
.
API базы данных поддерживает около двух десятков типов поиска; полная ссылка
можно найти в справочнике по поиску полей. Чтобы дать тебе
попробовать то, что доступно, вот некоторые из наиболее распространенных поисковых запросов, которые вы
вероятно использовать:
-
точно
«Точное» совпадение. Например:
>>> Entry.objects.get (headline__exact = "Кошка кусает собаку")
будет генерировать SQL в следующих строках:
SELECT ... WHERE headline = 'Кошка кусает собаку';
Если вы не укажете тип поиска, то есть если ваш аргумент ключевого слова
не содержит двойного подчеркивания - предполагается, что тип поиска
точный
.Например, следующие два оператора эквивалентны:
>>> Blog.objects.get (id__exact = 14) # Явная форма >>> Blog.objects.get (id = 14) # __exact подразумевается
Это сделано для удобства, потому что
точных поисков
являются обычным случаем.-
iexact
Соответствие без учета регистра. Итак, запрос:
>>> Blog. objects.get (name__iexact = "beatles blog")
Соответствует
Blog
под названием«Beatles Blog»
,«beatles blog»
, или
даже"БЕЛЫЙ БЛОГ"
.-
содержит
Тест на герметичность с учетом регистра. Например:
Entry.objects.get (headline__contains = 'Lennon')
Примерно переводится на этот SQL:
SELECT ... WHERE headline LIKE '% Lennon%';
Обратите внимание, что это будет соответствовать заголовку
«Сегодня Леннон почтил»
, но не
«сегодня Леннон почтил»
.Существует также версия без учета регистра,
icontains
.-
начинается с
,заканчивается с
- Начинается и заканчивается поиск соответственно.Это также
версии без учета регистра, называемыеistarts с
и
iendswith
.
Опять же, это только царапины на поверхности. Полную ссылку можно найти в
ссылка на поиск по полю.
Поиск, охватывающий отношения¶
Django предлагает мощный и интуитивно понятный способ «отслеживать» отношения в
поисков, автоматически заботясь о SQL JOIN
за вас, за
сцены. Чтобы охватить связь, используйте имя поля связанных полей
через модели, разделенные двойным подчеркиванием, пока не дойдете до поля, в котором
хотеть.
В этом примере извлекаются все объекты Entry
с Blog
с именем
это «Блог Битлз»
:
>>> Entry.objects.filter (blog__name = 'Beatles Blog')
Этот охват может быть сколь угодно глубоким.
Работает и в обратном направлении. Хотя можно настроить как
, по умолчанию вы имеете в виду «обратный»
отношения в поиске с использованием строчного имени модели.
В этом примере извлекаются все объекты Blog
, которые имеют хотя бы одну запись
чей заголовок
содержит «Леннон»
:
>>> Блог. objects.filter (entry__headline__contains = 'Леннон')
Если вы фильтруете несколько отношений и одно из промежуточных
models не имеет значения, которое удовлетворяет условию фильтрации, Django обработает
это как если бы там был пустой (все значения NULL
), но действительный объект.
Все это означает, что никаких ошибок возникать не будет. Например, в этом фильтре:
Blog.objects.filter (entry__authors__name = 'Lennon')
(если была родственная модель Author
), если не было author
связанный с записью, он будет обрабатываться, как если бы также не было name
прилагается, а не вызывает ошибку из-за отсутствия автора
.Обычно это именно то, что вы хотите. Единственный случай, когда это
может сбивать с толку, если вы используете , это пусто
. Таким образом:
Blog.objects.filter (entry__authors__name__isnull = True)
вернет объектов Blog
, которые имеют пустое имя
на author
и
также те, у которых есть пустой автор
в записи
. Если ты не хочешь
эти последние объекты можно написать:
Блог.объекты.фильтр (entry__authors__isnull = False, entry__authors__name__isnull = True)
Составные многозначные отношения¶
Когда вы фильтруете объект на основе
ManyToManyField
или наоборот
ForeignKey
, есть два разных типа фильтров
вам может быть интересно. Рассмотрим связь Blog
/ Entry
( Блог с
по Запись
является отношением «один ко многим»). Нам может быть интересно
поиск блогов, в которых есть запись, в заголовке которой содержится «Lennon», и
был опубликован в 2008 году.Или мы можем найти блоги, в которых есть запись с
«Леннон» в заголовке, а также опубликованная запись
в 2008 году. Поскольку с одним блогом
связано несколько записей,
оба этих запроса возможны и имеют смысл в некоторых ситуациях.
Такая же ситуация возникает с
ManyToManyField
. Например, если Запись
имеет
ManyToManyField
вызвал тегов
, мы могли бы захотеть
найти записи, связанные с тегами под названием «музыка» и «группы» , или нам может понадобиться
запись, содержащая тег с именем «музыка» и статусом «общедоступный» .
Чтобы справиться с обеими этими ситуациями, Django имеет последовательный способ обработки
фильтр ()
звонков. Все внутри
одиночный фильтр ()
вызов применяется
одновременно, чтобы отфильтровать элементы, соответствующие всем этим требованиям. Последовательный
filter ()
вызовов дополнительно ограничивают набор
объектов, но для многозначных отношений они применяются к любому объекту, связанному с
первичная модель, не обязательно те объекты, которые были выбраны
ранее фильтр ()
звонок.
Это может показаться немного запутанным, поэтому, надеюсь, это прояснит ситуацию. К
выберите все блоги, которые содержат записи с «Lennon» и в заголовке
и которые были опубликованы в 2008 году (та же запись, удовлетворяющая обоим условиям),
мы бы написали:
Blog. objects.filter (entry__headline__contains = 'Lennon', entry__pub_date__year = 2008)
Чтобы выбрать все блоги, которые содержат запись с «Леннон» в заголовке
, а также , запись, опубликованная в 2008 году, мы бы написали:
Блог.objects.filter (entry__headline__contains = 'Lennon'). filter (entry__pub_date__year = 2008)
Предположим, есть только один блог, в котором обе записи содержат «Леннон», и
записи с 2008 года, но ни одна из записей с 2008 года не содержала «Леннон» .
Первый запрос не вернет никаких блогов, но второй запрос вернет
тот единственный блог.
Во втором примере первый фильтр ограничивает набор запросов всеми этими
блоги, связанные с записями с «Леннон» в заголовке.Второй фильтр
ограничивает набор блогов далее теми, которые также связаны с записями
которые были опубликованы в 2008 году. Записи, выбранные вторым фильтром, могут или
могут не совпадать с записями в первом фильтре. Мы фильтруем
Блог
элементов с каждым оператором фильтра, а не элементов Entry
.
Примечание
Поведение filter ()
для запросов
которые охватывают многозначные отношения, как описано выше, не реализованы
эквивалентно для исключить ()
.Вместо,
условия в одном исключить ()
вызов не обязательно будет относиться к одному и тому же элементу.
Например, следующий запрос исключает блоги, содержащие и
записей с «Леннон» в заголовке и записей, опубликованных в 2008 г .:
Blog.objects.exclude ( entry__headline__contains = 'Леннон', entry__pub_date__year = 2008, )
Однако, в отличие от поведения при использовании
filter ()
, это не ограничивает блоги
на основе записей, удовлетворяющих обоим условиям.Для этого, т.е.
для выбора всех блогов, которые не содержат записей, опубликованных с помощью «Lennon»
которые были опубликованы в 2008 году, нужно сделать два запроса:
Blog. objects.exclude ( entry__in = Entry.objects.filter ( headline__contains = 'Леннон', pub_date__year = 2008, ), )
Фильтры могут ссылаться на поля в модели¶
В примерах, приведенных до сих пор, мы построили фильтры, которые сравнивают
значение модельного поля с константой.Но что, если вы хотите сравнить
значение поля модели с другим полем в той же модели?
Django предоставляет F-выражений
, чтобы
сравнения. Экземпляры F ()
действуют как ссылка на поле модели в
запрос. Эти ссылки затем можно использовать в фильтрах запросов для сравнения значений.
двух разных полей в одном экземпляре модели.
Например, чтобы найти список всех записей блога, к которым были добавлены дополнительные комментарии
чем pingbacks, мы создаем объект F ()
для ссылки на счетчик pingback,
и используйте этот объект F ()
в запросе:
>>> из django.db.models import F >>> Entry.objects. filter (number_of_comments__gt = F ('number_of_pingbacks'))
Django поддерживает использование сложения, вычитания, умножения,
деление, по модулю и степенная арифметика с F ()
объектами, оба с константами
и с другими объектами F ()
. Чтобы найти все записи блога с более чем
вдвое комментариев больше, чем пингбэков, модифицируем запрос:
>>> Entry.objects.filter (number_of_comments__gt = F ('number_of_pingbacks') * 2)
Чтобы найти все записи, у которых рейтинг меньше, чем
сумма количества пингбеков и комментариев, мы выдадим
запрос:
>>> Въезд.objects.filter (рейтинг__lt = F ('число_комментариев') + F ('число_pingbacks'))
Вы также можете использовать двойное подчеркивание, чтобы охватить отношения в
объект F ()
. Объект F ()
с двойным подчеркиванием представит
любые соединения, необходимые для доступа к связанному объекту. Например, чтобы получить все
записи, в которых имя автора совпадает с названием блога, мы могли бы
выдать запрос:
>>> Entry. objects.filter (авторы__name = F ('blog__name'))
Для полей даты и даты / времени вы можете добавить или вычесть
timedelta
объект.Следующее вернет все записи
которые были изменены более чем через 3 дня после публикации:
>>> from datetime import timedelta >>> Entry.objects.filter (mod_date__gt = F ('pub_date') + timedelta (days = 3))
Объекты F ()
поддерживают побитовые операции с помощью .bitand ()
, .bitor ()
,
.bitxor ()
, .bitrightshift ()
и .bitleftshift ()
. Например:
>>> F ('какое-то поле').битанд (16)
Оракул
Oracle не поддерживает побитовую операцию XOR.
Изменено в Django 3.1:
Добавлена поддержка .bitxor ()
.
Ярлык поиска
pk
¶
Для удобства Django предоставляет ярлык поиска pk
, что означает
"первичный ключ".
В примере модели Blog
первичным ключом является поле id
, поэтому эти
три утверждения эквивалентны:
>>> Блог. objects.get (id__exact = 14) # Явная форма >>> Blog.objects.get (id = 14) # __exact подразумевается >>> Blog.objects.get (pk = 14) # pk подразумевает id__exact
Использование pk
не ограничивается __exact
запросов - любой термин запроса
можно комбинировать с pk
для выполнения запроса по первичному ключу модели:
# Получить записи блогов с id 1, 4 и 7 >>> Blog.objects.filter (pk__in = [1,4,7]) # Получить все записи блога с id> 14 >>> Блог.objects.filter (pk__gt = 14)
pk
поиска также работают по объединениям. Например, эти три утверждения
эквивалент:
>>> Entry.objects.filter (blog__id__exact = 3) # Явная форма >>> Entry.objects.filter (blog__id = 3) # __exact подразумевается >>> Entry.objects.filter (blog__pk = 3) # __pk подразумевает __id__exact
Экранирование знаков процента и подчеркивания в
операторах LIKE
¶
Поиск по полю, который соответствует операторам SQL LIKE
( iexact
,
содержит
, иконок
, начинается с
, истартов с
, заканчивается с
и iendswith
) автоматически экранирует два специальных символа, используемых в
LIKE
утверждения - знак процента и подчеркивание. (В КАК
оператор, знак процента означает многосимвольный подстановочный знак, а
подчеркивание означает односимвольный подстановочный знак.)
Это означает, что все должно работать интуитивно, чтобы абстракция не просочилась.
Например, чтобы получить все записи, содержащие знак процента, используйте
знак процента как любой другой символ:
>>> Entry.objects.filter (headline__contains = '%')
Django позаботится о расценках за вас; полученный SQL будет выглядеть что-то
как это:
ВЫБРАТЬ... ГДЕ заголовок LIKE '% \ %%';
То же самое и с подчеркиванием. Обрабатываются как знаки процента, так и подчеркивания
для вас прозрачно.
Кэширование и
QuerySet
s¶
Каждый QuerySet
содержит кэш для минимизации
доступ к базе данных. Понимание того, как это работает, позволит вам писать максимально
эффективный код.
Во вновь созданном QuerySet
кеш
пустой. При первой оценке QuerySet
- и, следовательно, происходит запрос к базе данных - Django сохраняет результаты запроса в
кэш QuerySet
и возвращает результаты
которые были явно запрошены (например,g. , следующий элемент, если
QuerySet
перебирается). Последующий
оценки QuerySet
повторно используют кэшированные
полученные результаты.
Помните об этом поведении кеширования, потому что оно может вас укусить, если вы не используете
ваш QuerySet
правильно. Например,
следующее создаст два QuerySet
s, оцените
их и выбросить:
>>> print ([e.headline для e в Entry.objects.all ()]) >>> print ([e.pub_date для e в Entry.objects.all ()])
Это означает, что один и тот же запрос к базе данных будет выполнен дважды, фактически удваивая
загрузка вашей базы данных. Кроме того, есть вероятность, что эти два списка могут не включать
те же записи в базе данных, потому что Запись
могла быть добавлена или удалена
в доли секунды между двумя запросами.
Чтобы избежать этой проблемы, сохраните QuerySet
и
повторно использовать:
>>> queryset = Entry.objects.all () >>> print ([p. headline for p in queryset]) # Оценить набор запросов.>>> print ([p.pub_date for p in queryset]) # Повторно использовать кеш из оценки.
Когда
QuerySet
s не кэшируются¶
Наборы запросов не всегда кэшируют свои результаты. При оценке только часть из
набор запросов, кеш проверяется, но если он не заполнен, то элементы
возвращенные последующим запросом, не кэшируются. В частности, это означает, что
ограничение набора запросов с помощью среза массива или
index не будет заполнять кеш.
Например, повторное получение определенного индекса в объекте набора запросов приведет к запросу
в базе каждый раз:
>>> queryset = Запись.objects.all () >>> print (queryset [5]) # Запрашивает базу данных >>> print (queryset [5]) # Снова запрашивает базу данных
Однако, если весь набор запросов уже был оценен, кеш будет
проверил вместо этого:
>>> queryset = Entry.objects.all () >>> [запись для записи в наборе запросов] # Запрашивает базу данных >>> print (queryset [5]) # Использует кеш >>> print (queryset [5]) # Использует кеш
Вот несколько примеров других действий, которые приведут к созданию всего набора запросов.
оценивается и, следовательно, заполняет кеш:
>>> [запись для записи в наборе запросов] >>> bool (набор запросов) >>> запись в наборе запросов >>> список (набор запросов)
Примечание
Простая печать набора запросов не заполняет кеш.Это потому что
вызов __repr __ ()
возвращает только часть всего набора запросов.
Комплексный поиск с
Q
объектами¶
Запросы аргументов ключевого слова - в filter ()
,
и т.д. - соединяются «И» вместе. Если вам нужно выполнить более сложные запросы (для
Например, запросы с операторами OR
) можно использовать объектов Q
.
Объект Q
( django.db.models.Q
) является объектом
используется для инкапсуляции набора аргументов ключевых слов.Эти аргументы ключевого слова
указаны как в разделе «Поиск полей» выше.
Например, этот объект Q
инкапсулирует один запрос LIKE
:
из django. db.models import Q Q (question__startswith = 'Что')
Q
объекты можно комбинировать с помощью и
и |
оператора. Когда
используется на двух объектах Q
, он дает новый объект Q
.
Например, этот оператор дает один объект Q
, который представляет
«ИЛИ» из двух «question__startswith»
запросов:
Q (question__startswith = 'Кто') | Q (question__startswith = 'Что')
Это эквивалентно следующему предложению SQL WHERE
:
ГДЕ вопрос КАК "Кто%" ИЛИ вопрос КАК "Что%"
Вы можете составлять утверждения произвольной сложности, комбинируя объекты Q
с ,
и |
и используйте группировку в скобках.Также, Q
объекты могут быть инвертированы с помощью оператора ~
, что позволяет выполнять комбинированный поиск
которые сочетают как обычный запрос, так и отрицательный ( НЕ
) запрос:
Q (question__startswith = 'Кто') | ~ Q (pub_date__year = 2005)
Каждая функция поиска, которая принимает аргументы-ключевые слова
(например, фильтр ()
,
исключить ()
,
get ()
) также можно передать один или несколько
Q
объекты как позиционные (безымянные) аргументы. Если вы предоставите несколько
Q
аргументы объекта для функции поиска, аргументы будут "И"
вместе.Например:
Poll.objects.get ( Q (question__startswith = 'Кто'), Q (pub_date = date (2005, 5, 2)) | Q (pub_date = date (2005, 5, 6)) )
… примерно переводится в SQL:
ВЫБРАТЬ * из опросов, ГДЕ вопрос, КАК "Кто%" И (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
Функции поиска
могут смешивать использование объектов Q
и аргументов ключевого слова. Все
аргументы, предоставленные функции поиска (будь то аргументы ключевого слова или Q
объекты) соединяются вместе «И».Однако, если объект Q
предоставляется, он должен
предшествовать определению любых аргументов ключевого слова. Например:
Poll.objects.get ( Q (pub_date = date (2005, 5, 2)) | Q (pub_date = date (2005, 5, 6)), question__startswith = 'Кто', )
… будет допустимым запросом, эквивалентным предыдущему примеру; но:
# НЕВЕРНЫЙ ЗАПРОС Poll. objects.get ( question__startswith = 'Кто', Q (pub_date = date (2005, 5, 2)) | Q (pub_date = date (2005, 5, 6)) )
… недействителен.
Удаление объектов¶
Метод удаления, удобно, называется
удалить ()
. Этот метод немедленно удаляет
объект и возвращает количество удаленных объектов и словарь с
количество удалений по типу объекта. Пример:
>>> e.delete () (1, {'weblog.Entry': 1})
Вы также можете удалять объекты сразу. Каждый
QuerySet
имеет
delete ()
метод, который удаляет все
члены этого набора QuerySet
.
Например, при этом удаляются все объекты Entry
с pub_date
год
2005 год:
>>> Entry.objects.filter (pub_date__year = 2005) .delete () (5, {'webapp.Entry': 5})
Имейте в виду, что это будет, когда это возможно, выполняться исключительно на SQL, и
поэтому методы delete ()
отдельных экземпляров объекта не обязательно
быть вызванным во время процесса. Если вы указали собственный метод delete ()
в классе модели и хотите убедиться, что он вызывается, вам нужно будет
«Вручную» удалить экземпляры этой модели (например,g., перебирая
QuerySet
и вызов delete ()
на каждом
объект индивидуально) вместо использования большого количества
delete ()
метод
QuerySet
.
Когда Django удаляет объект, по умолчанию он имитирует поведение SQL
ограничение ON DELETE CASCADE
- другими словами, любые объекты, которые
внешние ключи, указывающие на удаляемый объект, будут удалены вместе с
Это. Например:
b = Blog.objects.get (pk = 1) # Это удалит блог и все его объекты Entry.b.delete ()
Это каскадное поведение настраивается через
on_delete
аргумент для
Иностранный ключ
.
Обратите внимание, что delete ()
- единственный
QuerySet
, который не отображается в
Менеджер
сам. Это предохранительный механизм для
предотвратить случайный запрос Entry.objects.delete ()
и
удаление всех записей. Если вы или хотите удалить все объекты, тогда
вы должны явно запросить полный набор запросов:
Въезд.objects.all (). delete ()
Одновременное обновление нескольких объектов¶
Иногда вы хотите установить в поле определенное значение для всех объектов в
QuerySet
. Вы можете сделать это с помощью
update ()
метод. Например:
# Обновить все заголовки с pub_date в 2007 году. Entry.objects.filter (pub_date__year = 2007) .update (headline = 'Все то же самое')
Можно установить только поля, не связанные с отношениями, и ForeignKey
поля, использующие этот метод.Чтобы обновить поле, не связанное с отношением, укажите новое значение
как константа. Чтобы обновить поля ForeignKey
, установите
новое значение, которое будет новым экземпляром модели, на который вы хотите указать. Например:
>>> b = Blog.objects.get (pk = 1) # Измените каждую запись так, чтобы она принадлежала этому блогу. >>> Entry.objects.all (). Update (blog = b)
Метод update ()
применяется мгновенно и возвращает количество строк
соответствует запросу (которое может не совпадать с количеством обновленных строк, если
некоторые строки уже имеют новое значение).Единственное ограничение на
QuerySet
обновляется тем, что он может только
доступ к одной таблице базы данных: основной таблице модели. Вы можете фильтровать по
связанных полей, но вы можете обновлять только столбцы в основном
стол. Пример:
>>> b = Blog.objects.get (pk = 1) # Обновите все заголовки, относящиеся к этому блогу. >>> Entry.objects.filter (blog = b) .update (headline = 'Все то же самое')
Имейте в виду, что метод update ()
преобразуется непосредственно в SQL
утверждение.Это массовая операция для прямых обновлений. Он не запускает
save ()
методов на ваших моделях или
pre_save
или post_save
сигналов (которые являются следствием вызова
сохранить ()
), или соблюдать
auto_now
поле вариант.
Если вы хотите сохранить каждый элемент в QuerySet
и убедитесь, что метод save ()
вызывается на
в каждом случае для этого не требуется никаких специальных функций. Петля
их и позвоните по номеру save ()
:
для элемента в my_queryset: элемент.спасти()
Вызовы обновления могут также использовать F-выражений
для
обновить одно поле на основе значения другого поля в модели. Это
особенно полезно для увеличения счетчиков в зависимости от их текущего значения. За
Например, чтобы увеличить счетчик пингбэков для каждой записи в блоге:
>>> Entry.objects.all (). Update (number_of_pingbacks = F ('number_of_pingbacks') + 1)
Однако, в отличие от объектов F ()
в предложениях filter и exclude, вы не можете
вводить соединения при использовании объектов F ()
в обновлении - вы можете только
ссылочные поля, локальные для обновляемой модели.Если вы попытаетесь представить
при соединении с объектом F ()
будет вызвано FieldError
:
# Это вызовет FieldError >>> Entry. objects.update (headline = F ('blog__name'))
Связанные объекты¶
Когда вы определяете связь в модели (т. Е.
Иностранный ключ
,
OneToOneField
или
ManyToManyField
) экземпляры этой модели будут иметь
удобный API для доступа к связанным объектам.
Используя модели в верхней части этой страницы, например, объект Entry
e
может получить связанный с ним объект Blog
, обратившись к атрибуту blog
:
e.блог
.
(За кадром эта функциональность реализована Python
дескрипторы. Это не должно иметь значения для
вы, но мы указываем на это здесь для любопытных.)
Django также создает API-аксессоры для «другой» стороны отношений -
ссылка из связанной модели на модель, определяющую отношение.
Например, объект Blog
b
имеет доступ к списку всех связанных
Запись
объектов через атрибут entry_set
: b. entry_set.all ()
.
Все примеры в этом разделе используют образец Блог
, Автор
и Запись
модели, определенные в верхней части этой страницы.
Отношения "один ко многим "¶
Вперед¶
Если модель имеет ForeignKey
, экземпляры этой модели
будет иметь доступ к связанному (внешнему) объекту через атрибут модели.
Пример:
>>> e = Entry.objects.get (id = 2) >>> е.blog # Возвращает связанный объект Blog.
Можно получить и установить через атрибут внешнего ключа. Как и следовало ожидать, изменения в
внешний ключ не сохраняется в базе данных, пока вы не вызовете
сохранить ()
. Пример:
>>> e = Entry.objects.get (id = 2) >>> e.blog = some_blog >>> e.save ()
Если для поля ForeignKey
установлено значение null = True
(т.е.
это позволяет NULL
значений), вы можете назначить None
, чтобы удалить отношение. Пример:
>>> e = Entry.objects.get (id = 2) >>> e.blog = Нет >>> e.save () # "UPDATE blog_entry SET blog_id = NULL ...;"
Прямой доступ к отношениям «один ко многим» кэшируется при первом
связанный объект доступен. Последующие обращения к внешнему ключу на том же
экземпляр объекта кэшируется. Пример:
>>> e = Entry.objects.get (id = 2) >>> print (e.blog) # Обращается к базе данных, чтобы получить связанный блог. >>> print (e.blog) # Не попадает в базу данных; использует кешированную версию.
Обратите внимание, что select_related ()
QuerySet
рекурсивно предварительно заполняет
кеш всех отношений "один ко многим" заранее. Пример:
>>> e = Entry.objects.select_related (). Get (id = 2) >>> print (e.blog) # Не попадает в базу данных; использует кешированную версию. >>> print (e.blog) # Не попадает в базу данных; использует кешированную версию.
Следить за отношениями «назад» ¶
Если модель имеет ForeignKey
, экземпляры
модель внешнего ключа будет иметь доступ к Manager
, который
возвращает все экземпляры первой модели. По умолчанию это
Manager
называется FOO_set
, где FOO
- это
название исходной модели в нижнем регистре. Этот менеджер
возвращается
QuerySets
, которые можно фильтровать и управлять, как описано в
Раздел «Получение объектов» выше.
Пример:
>>> b = Blog.objects.get (id = 1) >>> b.entry_set.all () # Возвращает все объекты Entry, относящиеся к Blog. # b.entry_set - это менеджер, который возвращает QuerySets. >>> б.entry_set.filter (заголовок__contains = 'Леннон') >>> b.entry_set.count ()
Вы можете изменить имя FOO_set
, установив
related_name
параметр в
ForeignKey
определение. Например, если Запись
модель была изменена на blog = ForeignKey (Blog, on_delete = models.CASCADE,
, приведенный выше пример кода будет выглядеть так:
related_name = 'entries')
>>> b = Blog.objects.get (id = 1) >>> б.Entry. all () # Возвращает все объекты Entry, относящиеся к Blog. # b.entries - это менеджер, который возвращает QuerySets. >>> b.entries.filter (headline__contains = 'Lennon') >>> b.entries.count ()
Использование специального реверсивного менеджера¶
По умолчанию используется RelatedManager
.
для обратных отношений является подклассом менеджера по умолчанию
для этой модели. Если вы хотите указать другого менеджера для данного
запрос можно использовать следующий синтаксис:
из django.модели импорта БД класс Entry (models.Model): # ... objects = models.Manager () # Диспетчер по умолчанию entry = EntryManager () # Пользовательский менеджер b = Blog.objects.get (id = 1) b.entry_set (менеджер = 'записи'). all ()
Если EntryManager
выполнил фильтрацию по умолчанию в своем get_queryset ()
, эта фильтрация будет применяться к вызову all ()
.
Указание настраиваемого реверсивного менеджера также позволяет вызывать его настраиваемый
методов:
г. entry_set (менеджер = 'записи'). is_published ()
Отношения "многие-ко-многим "46
Оба конца отношения «многие ко многим» получают автоматический доступ к другому через API.
конец. API работает аналогично описанной выше связи «один ко многим».
Одно отличие заключается в названии атрибута: модель, которая определяет
ManyToManyField
использует имя атрибута этого
само поле, тогда как «обратная» модель использует имя модели в нижнем регистре
исходная модель, плюс '_set'
(аналогично обратной связи "один ко многим").
Пример упрощает понимание:
e = Entry.objects.get (id = 3) e.authors.all () # Возвращает все объекты Author для этой записи. e.authors.count () e.authors.filter (name__contains = 'Джон') a = Author.objects.get (id = 5) a.entry_set.all () # Возвращает все объекты Entry для этого автора.
Как ForeignKey
,
ManyToManyField
может указать
связанное_имя
. В приведенном выше примере
если в ManyToManyField
в Entry
указано
related_name = 'entries'
, то каждый экземпляр Author
будет иметь
записей
атрибут вместо entry_set
.
Еще одно отличие от отношений "один ко многим" состоит в том, что в дополнение к модели
экземпляров, методы add ()
, set ()
и remove ()
для многих-ко-многим
отношения принимают значения первичного ключа. Например, если e1
и e2
являются
Entry
instance, тогда эти set ()
вызовов работают идентично:
a = Author.objects.get (id = 5) a.entry_set.set ([e1, e2]) a.entry_set.set ([e1.pk, e2.pk])
Индивидуальные отношения¶
Отношения «один к одному» очень похожи на отношения «многие к одному».если ты
определите OneToOneField
в вашей модели, экземпляры
эта модель будет иметь доступ к связанному объекту через атрибут
модель.
Например:
класс EntryDetail (models.Model): entry = models.OneToOneField (Entry, on_delete = models.CASCADE) details = models.TextField () ed = EntryDetail.objects.get (id = 2) ed.entry # Возвращает связанный объект Entry.
Разница заключается в «обратных» запросах. Связанная модель в индивидуальном порядке
отношение также имеет доступ к объекту Manager
, но
что Manager
представляет собой отдельный объект, а не
коллекция предметов:
e = Вход.objects.get (id = 2) e.entrydetail # возвращает связанный объект EntryDetail
Если этим отношениям не назначен ни один объект, Django вызовет
исключение DoesNotExist
.
Экземпляры могут быть назначены обратной связи таким же образом, как и
вы бы назначили прямую связь:
Как возможны обратные отношения? ¶
Другие объектно-реляционные преобразователи требуют, чтобы вы определяли отношения на обоих
стороны. Разработчики Django считают, что это нарушение DRY (не
Повторите себя), поэтому Django требует только определить
отношения на одном конце.
Но как это возможно, учитывая, что класс модели не знает, какой другой
классы модели связаны с ним, пока не будут загружены другие классы модели?
Ответ кроется в реестре приложений
. Когда Джанго
запускается, он импортирует каждое приложение, указанное в INSTALLED_APPS
, и
затем модуль модели
внутри каждого приложения. Каждый раз, когда появляется новый класс модели
Django добавляет обратные отношения ко всем связанным моделям. Если
связанные модели еще не были импортированы, Django отслеживает
отношений и добавляет их, когда связанные модели в конечном итоге импортируются.
По этой причине особенно важно, чтобы все модели, которые вы используете
быть определенным в приложениях, перечисленных в INSTALLED_APPS
. Иначе,
обратные отношения могут не работать должным образом.
запросов и мутаций | GraphQL
На этой странице вы подробно узнаете о том, как запрашивать сервер GraphQL.
Fields #
В самом простом случае GraphQL запрашивает определенные поля для объектов. Давайте начнем с рассмотрения очень простого запроса и результата, который мы получим при его запуске:
Вы сразу увидите, что запрос имеет точно такую же форму, что и результат.Это важно для GraphQL, потому что вы всегда получаете то, что ожидаете, и сервер точно знает, какие поля запрашивает клиент.
Поле name
возвращает тип String
, в данном случае имя главного героя «Звездных войн» «R2-D2»
.
О, еще одна вещь - запрос выше интерактивный . Это означает, что вы можете изменить его как хотите и увидеть новый результат. Попробуйте добавить поле
sizesIn
к объектуhero
в запросе и посмотрите новый результат.
В предыдущем примере мы просто запросили имя нашего героя, который вернул строку, но поля также могут ссылаться на объекты. В этом случае вы можете сделать подвыбор полей для этого объекта. Запросы GraphQL могут перемещаться по связанным объектам и их полям, позволяя клиентам извлекать множество связанных данных за один запрос, вместо того, чтобы выполнять несколько циклов туда и обратно, как это было бы необходимо в классической архитектуре REST.
Обратите внимание, что в этом примере поле друзей
возвращает массив элементов.Запросы GraphQL выглядят одинаково как для отдельных элементов, так и для списков элементов, однако мы знаем, какой из них ожидать, исходя из того, что указано в схеме.
Аргументы #
Если бы мы могли только перемещаться по объектам и их полям, GraphQL уже был бы очень полезным языком для выборки данных. Но когда вы добавляете возможность передавать аргументы в поля, все становится намного интереснее.
В такой системе, как REST, вы можете передавать только один набор аргументов - параметры запроса и сегменты URL в вашем запросе.Но в GraphQL каждое поле и вложенный объект может получить свой собственный набор аргументов, что делает GraphQL полной заменой для выполнения множественных выборок API. Вы даже можете передавать аргументы в скалярные поля для реализации преобразования данных один раз на сервере, а не на каждом клиенте отдельно.
Аргументы могут быть разных типов. В приведенном выше примере мы использовали тип Enumeration, который представляет один из конечного набора параметров (в данном случае единицы длины: METER
или FOOT
).GraphQL поставляется с набором типов по умолчанию, но сервер GraphQL также может объявлять свои собственные настраиваемые типы, если они могут быть сериализованы в ваш транспортный формат.
Подробнее о системе типов GraphQL здесь.
Псевдонимы #
Если у вас есть зоркий глаз, вы могли заметить, что, поскольку поля объекта результата соответствуют имени поля в запросе, но не содержат аргументов, вы не можете напрямую запросить то же поле. с разными аргументами. Вот почему вам нужно псевдонима - они позволяют вам переименовывать результат поля во что угодно.
В приведенном выше примере два поля hero
конфликтуют, но, поскольку мы можем присвоить им разные имена, мы можем получить оба результата в одном запросе.
Fragments #
Допустим, у нас есть относительно сложная страница в нашем приложении, которая позволяет нам смотреть на двух героев бок о бок вместе с их друзьями. Вы можете себе представить, что такой запрос может быстро усложниться, потому что нам нужно будет повторить поля хотя бы один раз - по одному для каждой стороны сравнения.
Вот почему GraphQL включает многоразовые блоки, называемые фрагментами . Фрагменты позволяют создавать наборы полей, а затем включать их в запросы, когда это необходимо. Вот пример того, как вы могли бы решить вышеуказанную ситуацию с помощью фрагментов:
Вы можете видеть, как вышеупомянутый запрос был бы довольно часто повторяющимся, если бы поля повторялись. Концепция фрагментов часто используется для разделения сложных требований к данным приложения на более мелкие части, особенно когда вам нужно объединить множество компонентов пользовательского интерфейса с разными фрагментами в одну исходную выборку данных.
Использование переменных внутри фрагментов #
Для фрагментов возможен доступ к переменным, объявленным в запросе или мутации. См. Переменные.
Название операции #
До сих пор мы использовали сокращенный синтаксис, в котором мы опускали ключевое слово query
и имя запроса, но в производственных приложениях полезно использовать их, чтобы сделать наш код менее неоднозначным.
Вот пример, который включает ключевое слово , запрос
как тип операции и HeroNameAndFriends
как имя операции :
Тип операции либо запрос , мутация , либо подписка и описание подписки какой тип операции вы собираетесь делать.Тип операции является обязательным, если вы не используете сокращенный синтаксис запроса, и в этом случае вы не можете указать имя или определения переменных для своей операции.
Имя операции - понятное и явное имя для вашей операции. Он требуется только в многооперационных документах, но его использование приветствуется, поскольку он очень полезен для отладки и ведения журналов на стороне сервера.
Когда что-то идет не так (вы видите ошибки либо в сетевых журналах, либо в журналах вашего сервера GraphQL), легче идентифицировать запрос в вашей кодовой базе по имени, чем пытаться расшифровать содержимое.Думайте об этом как об имени функции на вашем любимом языке программирования.
Например, в JavaScript мы можем легко работать только с анонимными функциями, но когда мы даем функции имя, ее легче отследить, отладить наш код,
и записывать, когда он вызывается. Точно так же имена запросов и мутаций GraphQL, наряду с именами фрагментов, могут быть полезным инструментом отладки на стороне сервера для идентификации
разные запросы GraphQL.
Переменные #
До сих пор мы записывали все наши аргументы внутри строки запроса.Но в большинстве приложений аргументы для полей будут динамическими: например, может быть раскрывающийся список, который позволяет вам выбрать, какой эпизод «Звездных войн» вам интересен, или поле поиска, или набор фильтров.
Не рекомендуется передавать эти динамические аргументы непосредственно в строке запроса, потому что тогда нашему клиентскому коду потребуется динамически манипулировать строкой запроса во время выполнения и сериализовать ее в специфичный для GraphQL формат. Вместо этого в GraphQL есть первоклассный способ вычленить динамические значения из запроса и передать их как отдельный словарь. Эти значения называются переменными .
Когда мы начинаем работать с переменными, нам нужно сделать три вещи:
- Заменить статическое значение в запросе на
$ variableName
- Объявить
$ variableName
как одну из переменных, принимаемых запросом - Пройти
variableName: значение
в отдельном, специфическом для транспорта (обычно JSON) словаре переменных
Вот как это выглядит все вместе:
Теперь в нашем клиентском коде мы можем просто передать другую переменную вместо того, чтобы создавать совершенно новый запрос.Это также в целом хорошая практика для обозначения того, какие аргументы в нашем запросе должны быть динамическими - мы никогда не должны выполнять интерполяцию строк для построения запросов из значений, предоставленных пользователем.
Определения переменных #
Определения переменных - это часть, которая в запросе выше выглядит как ($ Episode: Episode)
. Он работает так же, как определения аргументов для функции на типизированном языке. В нем перечислены все переменные с префиксом $
, за которым следует их тип, в данном случае Episode
.
Все объявленные переменные должны быть скалярами, перечислениями или типами входных объектов. Поэтому, если вы хотите передать сложный объект в поле, вам нужно знать, какой тип ввода соответствует на сервере. Узнайте больше о типах входных объектов на странице схемы.
Определения переменных могут быть необязательными или обязательными. В приведенном выше случае, поскольку нет !
рядом с типом Episode
, это необязательно. Но если поле, в которое вы передаете переменную, требует аргумента, отличного от NULL, тогда переменная также должна быть обязательной.
Чтобы узнать больше о синтаксисе этих определений переменных, полезно изучить язык схем GraphQL. Язык схемы подробно объясняется на странице схемы.
Переменные по умолчанию #
Значения по умолчанию также можно присвоить переменным в запросе, добавив значение по умолчанию после объявления типа.
запрос HeroNameAndFriends ($ эпизод: эпизод = JEDI) {
герой (эпизод: $ эпизод) {
имя
друзья {
имя
}
}
000}
значения по умолчанию -
предоставляется для всех переменных, вы можете вызывать запрос без передачи каких-либо переменных.Если какие-либо переменные передаются как часть словаря переменных, они переопределяют значения по умолчанию.
Директивы #
Выше мы обсуждали, как переменные позволяют избежать ручной интерполяции строк для построения динамических запросов. Передача переменных в аргументах решает довольно большой класс этих проблем, но нам также может потребоваться способ динамического изменения структуры и формы наших запросов с помощью переменных. Например, мы можем представить себе компонент пользовательского интерфейса, который имеет сводное и подробное представление, в котором одно включает больше полей, чем другое.
Давайте построим запрос для такого компонента:
Попробуйте отредактировать указанные выше переменные, чтобы вместо этого передать true
для withFriends
, и посмотрите, как изменится результат.
Нам нужно было использовать новую функцию в GraphQL, называемую директивой . Директива может быть прикреплена к полю или включению фрагмента и может влиять на выполнение запроса любым способом, который пожелает сервер. Базовая спецификация GraphQL включает ровно две директивы, которые должны поддерживаться любой соответствующей спецификацией реализацией сервера GraphQL:
-
@include (if: Boolean)
Включайте это поле в результат, только если аргументtrue
. -
@skip (if: Boolean)
Пропустить это поле, если аргументtrue
.
Директивы могут быть полезны для выхода из ситуаций, когда вам в противном случае пришлось бы выполнять манипуляции со строками для добавления и удаления полей в вашем запросе. Реализации сервера могут также добавлять экспериментальные функции, определяя совершенно новые директивы.
Mutations #
Большинство обсуждений GraphQL сосредоточено на выборке данных, но любая полноценная платформа данных также нуждается в способе модификации данных на стороне сервера.
В REST любой запрос может вызвать некоторые побочные эффекты на сервере, но по соглашению предлагается не использовать запросы GET
для изменения данных. GraphQL похож - технически любой запрос может быть реализован, чтобы вызвать запись данных. Однако полезно установить соглашение, согласно которому любые операции, вызывающие запись, должны отправляться явно через мутацию.
Как и в запросах, если поле мутации возвращает тип объекта, вы можете запросить вложенные поля.Это может быть полезно для получения нового состояния объекта после обновления. Давайте посмотрим на простой пример мутации:
Обратите внимание, как поле createReview
возвращает поля звезд
и комментариев
только что созданного обзора. Это особенно полезно при изменении существующих данных, например, при увеличении поля, поскольку мы можем изменять и запрашивать новое значение поля с помощью одного запроса.
Вы также можете заметить, что в этом примере переданная нами переменная review
не является скаляром. Это входной объект типа , особый тип объекта, который может быть передан в качестве аргумента. Узнайте больше о типах ввода на странице схемы.
Несколько полей в мутациях #
Мутация может содержать несколько полей, как и запрос. Есть одно важное различие между запросами и мутациями, кроме имени:
В то время как поля запроса выполняются параллельно, поля мутации выполняются последовательно, одно за другим.
Это означает, что если мы отправим две мутации incrementCredits
в одном запросе, первая гарантированно завершится до начала второй, гарантируя, что мы не закончим с состоянием гонки с самими собой.
Встроенные фрагменты #
Как и многие другие системы типов, схемы GraphQL включают возможность определять интерфейсы и типы объединения. Узнайте о них в руководстве по схеме.
Если вы запрашиваете поле, которое возвращает интерфейс или тип объединения, вам нужно будет использовать встроенные фрагменты для доступа к данным базового конкретного типа. Это проще всего увидеть на примере:
В этом запросе поле hero
возвращает тип Character
, который может быть либо Human
, либо Droid
в зависимости от аргумента эпизода
.При прямом выборе вы можете запрашивать только поля, которые существуют в интерфейсе символов
, например, name
.
Чтобы запросить поле для конкретного типа, вам необходимо использовать встроенный фрагмент с условием типа. Поскольку первый фрагмент помечен как ... на Droid
, поле primaryFunction
будет выполняться только в том случае, если Character
, возвращенный из hero
, относится к типу Droid
. Аналогично для поля height
для типа Human
.
Именованные фрагменты также могут использоваться таким же образом, поскольку именованный фрагмент всегда имеет присоединенный тип.
Мета-поля #
Учитывая, что в некоторых ситуациях вы не знаете, какой тип вы получите обратно от службы GraphQL, вам нужен какой-то способ определить, как обрабатывать эти данные на клиенте. GraphQL позволяет вам запрашивать __typename
, метаполе, в любой момент запроса, чтобы получить имя типа объекта в этой точке.
В приведенном выше запросе search
возвращает тип объединения, который может быть одним из трех вариантов.Было бы невозможно отличить разные типы от клиента без поля __typename
.
Сервисы GraphQL предоставляют несколько мета-полей, остальные из которых используются для раскрытия системы интроспекции.
Запрос | GORM - фантастическая библиотека ORM для Golang, удобная для разработчиков.
Получение одного объекта
GORM предоставляет First
, Take
, Last
метод для получения одного объекта из базы данных, он добавляет LIMIT 1
условие при запросе к базе данных и возвращает ошибку ErrRecordNotFound
если запись не найдена.
|
Если вы хотите избежать ошибки
ErrRecordNotFound
, вы можете использоватьFind 9000b, например
, методdd
.Ограничение (1) .Find (& user)Find
принимает как данные структуры, так и данные среза
Метод First
, Last
найдет порядок первой / последней записи по первичному ключу, он работает только при запросе со структурой или предоставляет значение модели, если первичный ключ не определен для текущей модели, будет упорядочен по первому полю, например:
var user User |
Получение объектов с первичным ключом
Объекты могут быть получены с использованием первичного ключа с помощью встроенных условий, если первичный ключ является числом. Будьте особенно осторожны со строками, чтобы избежать SQL-инъекции, подробности см. В разделе «Безопасность»
дб.Первый (& user, 10) |
Если первичный ключ представляет собой строку типа uuid, ее нужно написать так:
db. First (& user, "id =?", "1b74413f-f3b8-409f-ac47-e8c062e3472a") |
Получение всех объектов
08
результат.RowsAffected результат
.Ошибка
Условия
Строковые условия
|
Условия структуры и карты
|
ПРИМЕЧАНИЕ При запросе с помощью struct GORM будет запрашивать только с ненулевые поля, это означает, что если значение вашего поля равно
0
,''
,false
или другие нулевые значения, оно не будет использоваться для построения условий запроса, например:
db.Where (& Пользователь {Имя: "jinzhu", Возраст: 0}).Найти (и пользователи) |
Вы можете использовать карту для построения условия запроса, она будет использовать все значения, например:
db.Where (map [string] interface {} {"Name": "jinzhu", "Age": 0}). Find (& users) |
Или обратитесь Укажите поиск структуры поля
Укажите поля поиска структуры
При поиске с помощью структуры вы можете использовать ее имя поля или имя базы данных в качестве аргументов для указания полей поиска, например:
дб.Где (& Пользователь {Имя: "jinzhu"}, "имя", "Возраст"). Найти (& пользователей) |
Встроенное состояние
Работает аналогично , где
.
|
Not Conditions
Build NOT условия, работает аналогично Где
db. Not ("name =?", "Jinzhu"). Первый (& пользователь) |
Или Условия
db.Where ("роль =? "," admin "). Или (" role =? "," super_admin "). Найдите (& users) |
Также ознакомьтесь с условиями группы в расширенном запросе, его можно использовать для написания сложного SQL
Выбор определенных полей
Укажите поля, которые вы хотите получить из базы данных, по умолчанию выберите все поля
дб. Выберите ("имя", "возраст"). Найдите (& пользователей) |
Также проверьте поля Smart Select
Заказ
Указать порядок при извлечении записей из БД
db.Order ("возраст по убыванию, имя"). Найти (& пользователи) |
Limit & Offset
Limit
укажите максимальное количество записей для извлечения
Offset
укажите количество записи, которые нужно пропустить, прежде чем начать возвращать записи
дб. Предел (3) .Найти (& пользователи) |
Checkout Pagination для того, чтобы сделать paginator
Группа и наличие
тип result struct { |
Distinct
Выбор различных значений из модели
дб.Distinct ("name", "age"). Order ("name, age desc"). Find (& results) |
Distinct
работает с Pluck
, Count
также
Соединения
Укажите условия соединения
type result struct { |
Предварительная загрузка объединений
Вы можете использовать объединений
ассоциаций активной загрузки с одним SQL, например:
db. Joins («Компания»). Найти (и пользователей) |
Подробнее см. Предварительная загрузка (Активная загрузка)
Сканировать
Результаты сканирования в структуру, аналогичную Найти
type Result struct { |
get-query-execution — AWS CLI 1.19.7 Справочник команд
Примечание:
Вы просматриваете документацию для более старой основной версии AWS CLI (версия 1).
AWS CLI версии 2, последняя основная версия AWS CLI, теперь стабильна и рекомендуется для общего использования. Чтобы просмотреть эту страницу для AWS CLI версии 2, щелкните
здесь.
Для получения дополнительной информации см. AWS CLI версии 2.
инструкции по установке
и
руководство по миграции.
[ aws . Афина ]
Описание
Возвращает информацию об одном выполнении запроса, если у вас есть доступ к рабочей группе, в которой выполнялся запрос.Каждый раз, когда выполняется запрос, информация о выполнении запроса сохраняется с уникальным идентификатором.
См. Также: Документация по API AWS
Описание глобальных параметров см. В ‘aws help’ .
Сводка
получить-запрос-выполнение --query-execution-id <значение> [--cli-input-json <значение>] [--generate-cli-skeleton <значение>]
Опции
— идентификатор-выполнения-запроса (строка)
Уникальный идентификатор выполнения запроса.
—cli-input-json (строка)
Выполняет служебную операцию на основе предоставленной строки JSON. Строка JSON соответствует формату, предоставленному —generate-cli-skeleton. Если в командной строке указаны другие аргументы, значения CLI переопределят значения, предоставленные JSON. Невозможно передать произвольные двоичные значения, используя значение, предоставленное JSON, поскольку строка будет восприниматься буквально.
—generate-cli-скелет (строка)
Выводит скелет JSON на стандартный вывод без отправки запроса API.Если предоставлено без значения или ввода значения, печатает образец входного JSON, который можно использовать в качестве аргумента для —cli-input-json. Если предоставляется с выходным значением, он проверяет входные данные команды и возвращает образец выходного JSON для этой команды.
Описание глобальных параметров см. В ‘aws help’ .
Примеры
Для возврата информации о выполнении запроса
Следующий пример выполнения get-query возвращает информацию о запросе с указанным идентификатором запроса.
aws athena получить выполнение запроса \ - идентификатор-выполнения-запроса a1b2c3d4-5678-90ab-cdef-ПРИМЕР 11111
Выход:
{ "QueryExecution": { "QueryExecutionId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111", «Запрос»: «выберите дату, местоположение, браузер, URI, статус из cloudfront_logs, где метод = 'ПОЛУЧИТЬ 'и статус = 200 и местоположение вроде' SFO% 'limit 10 ", "StatementType": "DML", "ResultConfiguration": { "OutputLocation": "s3: // awsdoc-example-bucket / a1b2c3d4-5678-90ab-cdef-EXAMPLE11111.csv " }, "QueryExecutionContext": { «База данных»: «моя база данных», "Каталог": "awsdatacatalog" }, "Положение дел": { «Состояние»: «УСПЕШНО», "SubmissionDateTime": 1593469842.665, "CompletionDateTime": 1593469846.486 }, "Статистика": { "EngineExecutionTimeInMillis": 3600, «DataScannedInBytes»: 203089, «TotalExecutionTimeInMillis»: 3821, «QueryQueueTimeInMillis»: 267, «QueryPlanningTimeInMillis»: 1175 }, «Рабочая группа»: «AthenaAdmin» } }
Дополнительные сведения см. В разделе Выполнение SQL-запросов с помощью Amazon Athena в Руководстве пользователя Amazon Athena .
Выход
QueryExecution -> (структура)
Информация о выполнении запроса.
QueryExecutionId -> (строка)
Уникальный идентификатор для каждого выполнения запроса.
Запрос -> (строка)
Операторы запроса SQL, которые выполнялись при выполнении запроса.
StatementType -> (строка)
Тип выполненного оператора запроса. DDL указывает операторы запроса DDL.DML указывает операторы запроса DML (язык манипулирования данными), такие как CREATE TABLE AS SELECT. UTILITY указывает операторы запроса, отличные от DDL и DML, такие как SHOW CREATE TABLE или DESCRIBE table.
ResultConfiguration -> (структура)
Место в Amazon S3, где хранились результаты запроса и использовалась опция шифрования, если таковая имеется, для результатов запроса. Они известны как «настройки на стороне клиента». Если параметры рабочей группы переопределяют параметры на стороне клиента, то запрос использует расположение результатов запроса и конфигурацию шифрования, указанную для рабочей группы.
OutputLocation -> (строка)
Местоположение в Amazon S3, где хранятся результаты вашего запроса, например s3: // path / to / query / bucket /. Чтобы выполнить запрос, необходимо указать расположение результатов запроса одним из способов: либо для отдельных запросов с использованием этого параметра (на стороне клиента), либо в рабочей группе с помощью WorkGroupConfiguration. Если ни один из них не задан, Athena выдает ошибку о том, что местоположение вывода не указано. Для получения дополнительной информации см. Результаты запроса. Если параметры рабочей группы переопределяют параметры на стороне клиента, то запрос использует параметры, указанные для рабочей группы.См. WorkGroupConfiguration $ EnforceWorkGroupConfiguration.
Конфигурация шифрования -> (структура)
Если результаты запроса зашифрованы в Amazon S3, указывает используемый вариант шифрования (например, SSE-KMS или CSE-KMS) и ключевую информацию. Это настройка на стороне клиента. Если параметры рабочей группы переопределяют параметры на стороне клиента, тогда запрос использует конфигурацию шифрования, указанную для рабочей группы, а также использует расположение для хранения результатов запроса, указанное в рабочей группе.См. Разделы WorkGroupConfiguration $ EnforceWorkGroupConfiguration и Параметры рабочей группы, переопределяющие параметры на стороне клиента.
EncryptionOption -> (строка)
Указывает, используется ли шифрование на стороне сервера Amazon S3 с ключами, управляемыми Amazon S3 (SSE-S3), шифрование на стороне сервера с ключами, управляемыми KMS (SSE-KMS), или шифрование на стороне клиента с ключами, управляемыми KMS (CSE-KMS). ) используется.
Если запрос выполняется в рабочей группе и рабочая группа переопределяет параметры на стороне клиента, то используются параметры шифрования рабочей группы.Он указывает, должны ли быть зашифрованы результаты запроса для всех запросов, выполняемых в этой рабочей группе.
KmsKey -> (строка)
Для SSE-KMS и CSE-KMS это ARN или идентификатор ключа KMS.
QueryExecutionContext -> (структура)
База данных, в которой произошло выполнение запроса.
База данных -> (строка)
Имя базы данных, используемой при выполнении запроса.
Каталог -> (строка)
Имя каталога данных, используемого при выполнении запроса.
Статус -> (структура)
Дата завершения, текущее состояние, время отправки и причина изменения состояния (если применимо) для выполнения запроса.
Состояние -> (строка)
Состояние выполнения запроса. QUEUED указывает, что запрос был отправлен в службу, и Athena выполнит запрос, как только ресурсы станут доступны. RUNNING указывает, что запрос находится в фазе выполнения. SUCCEEDED означает, что запрос выполнен без ошибок. FAILED означает, что запрос обнаружил ошибку и не завершил обработку. ОТМЕНА означает, что ввод пользователя прервал выполнение запроса.
Примечание
Athena автоматически повторяет ваши запросы в случае определенных временных ошибок. В результате вы можете увидеть переход состояния запроса с RUNNING или FAILED на QUEUED.
StateChangeReason -> (строка)
Дополнительные сведения о статусе запроса.
SubmissionDateTime -> (отметка времени)
Дата и время отправки запроса.
CompletionDateTime -> (отметка времени)
Дата и время завершения запроса.
Статистика -> (структура)
Статистика выполнения запроса, такая как объем просканированных данных, время, затраченное на обработку запроса, и тип выполненного оператора.
EngineExecutionTimeInMillis -> (длинный)
Количество миллисекунд, которое потребовалось для выполнения запроса.
DataScannedInBytes -> (длинный)
Число байтов в запрошенных данных.
DataManifestLocation -> (строка)
Расположение и имя файла манифеста данных. Файл манифеста сохраняется в папке результатов запроса Athena в Amazon S3. Файл манифеста отслеживает файлы, которые запрос написал в Amazon S3. Если запрос не выполняется, файл манифеста также отслеживает файлы, которые запрос предназначен для записи. Манифест полезен для идентификации потерянных файлов в результате неудачного запроса. Дополнительные сведения см. В разделе «Работа с результатами запросов, выходными файлами и историей запросов» в Руководстве пользователя Amazon Athena .
TotalExecutionTimeInMillis -> (длинный)
Количество миллисекунд, которое Афина потратила на выполнение запроса.
QueryQueueTimeInMillis -> (длинный)
Количество миллисекунд, в течение которых запрос находился в очереди запросов в ожидании ресурсов. Обратите внимание, что при возникновении временных ошибок Athena может автоматически добавить запрос обратно в очередь.
QueryPlanningTimeInMillis -> (длинный)
Количество миллисекунд, которое Афина потратила на планирование потока обработки запроса.Сюда входит время, потраченное на получение разделов таблицы из источника данных. Обратите внимание: поскольку механизм запросов выполняет планирование запросов, время планирования запросов является подмножеством времени обработки запросов.
ServiceProcessingTimeInMillis -> (длинный)
Количество миллисекунд, которое потребовалось Афине для завершения и публикации результатов запроса после того, как механизм запросов завершил выполнение запроса.
WorkGroup -> (строка)
Имя рабочей группы, в которой выполнялся запрос.
EngineVersion -> (конструкция)
Версия механизма, выполнившего запрос.
SelectedEngineVersion -> (строка)
Версия движка, запрошенная пользователем. Возможные значения определяются выводом ListEngineVersions, включая Auto. По умолчанию установлено Авто.
EffectiveEngineVersion -> (строка)
Только чтение. Версия движка, на которой выполняется запрос. Если пользователь запрашивает действительную версию ядра, отличную от Auto, действующая версия ядра совпадает с версией ядра, запрошенной пользователем.Если пользователь запрашивает Авто, эффективная версия движка выбирается Афиной. Когда запрос на обновление версии ядра выполняется операцией CreateWorkGroup или UpdateWorkGroup, поле EffectiveEngineVersion игнорируется.
Начало работы с SQL-запросами в Azure Cosmos DB
- 000Z» data-article-date-source=»ms.date»> 02.02.2021
- 4 минуты на чтение
В этой статье
ПРИМЕНЯЕТСЯ К:
SQL API
В учетных записях API SQL Azure Cosmos DB есть два способа чтения данных:
Точка читает — Вы можете выполнить поиск ключа / значения для одного элемента с идентификатором и ключом раздела.Код элемента с идентификатором и комбинация клавиш раздела являются ключом, а сам элемент является значением. Для документа размером 1 КБ чтение точки обычно стоит 1 единицу запроса с задержкой менее 10 мс. При чтении точек возвращается один элемент.
Вот несколько примеров того, как Point читает с каждым SDK:
SQL-запросы — Вы можете запрашивать данные, записывая запросы с использованием языка структурированных запросов (SQL) в качестве языка запросов JSON. Запросы всегда стоят не менее 2,3 единицы запроса и, как правило, имеют более высокую и переменную задержку, чем точечные чтения. Запросы могут вернуть много элементов.
Большинство рабочих нагрузок с интенсивным чтением в Azure Cosmos DB используют комбинацию точечного чтения и запросов SQL. Если вам просто нужно прочитать один элемент, точечное чтение дешевле и быстрее, чем запросы. При чтении точек не требуется использовать механизм запросов для доступа к данным, и они могут считываться напрямую. Конечно, не для всех рабочих нагрузок возможно чтение данных исключительно с использованием точечного чтения, поэтому поддержка SQL в качестве языка запросов и индексация без привязки к схеме обеспечивают более гибкий способ доступа к вашим данным.
Вот несколько примеров того, как выполнять SQL-запросов с каждым SDK:
В оставшейся части этого документа показано, как начать писать запросы SQL в Azure Cosmos DB. SQL-запросы можно запускать через SDK или портал Azure.
Загрузить образцы данных
В учетной записи SQL API Cosmos DB откройте проводник данных, чтобы создать контейнер с именем Families
. После того, как он будет создан, используйте браузер структур данных, чтобы найти и открыть его. В вашем контейнере Families
вы увидите опцию Items
прямо под именем контейнера.Откройте эту опцию, и вы увидите кнопку в строке меню в центре экрана, чтобы создать «Новый элемент». Вы будете использовать эту функцию для создания элементов JSON ниже.
Создание элементов JSON
Следующие 2 элемента JSON представляют собой документы о семействах Андерсена и Уэйкфилда. Они включают родителей, детей и их домашних животных, адрес и регистрационную информацию.
Первый элемент содержит строки, числа, логические значения, массивы и вложенные свойства:
{
"id": "Семья Андерсена",
"lastName": "Андерсен",
"родители": [
{"firstName": "Томас"},
{"firstName": "Мэри Кей"}
],
"дети": [
{
"firstName": "Генриетта Таулов",
"женский пол",
«оценка»: 5,
"домашние животные": [{"givenName": "Пушистый"}]
}
],
"address": {"state": "WA", "county": "King", "city": "Сиэтл"},
"creationDate": 1431620472,
"isRegistered": true
}
Во втором элементе используется givenName
и familyName
вместо firstName
и lastName
:
{
"id": "WakefieldFamily",
"родители": [
{"familyName": "Wakefield", "givenName": "Робин"},
{"familyName": "Миллер", "givenName": "Бен"}
],
"дети": [
{
"familyName": "Мерриам",
"givenName": "Джесси",
"женский пол",
"1-й класс,
"домашние питомцы": [
{"givenName": "Гуфи"},
{"givenName": "Тень"}
]
},
{
"familyName": "Миллер",
"givenName": "Лиза",
"женский пол",
"оценка": 8}
],
"адрес": {"штат": "Нью-Йорк", "округ": "Манхэттен", "город": "Нью-Йорк"},
"creationDate": 1431620462,
"isRegistered": ложь
}
Запрос элементов JSON
Попробуйте выполнить несколько запросов к данным JSON, чтобы понять некоторые ключевые аспекты языка запросов SQL в Azure Cosmos DB.
Следующий запрос возвращает элементы, для которых поле id
соответствует AndersenFamily
. Поскольку это запрос SELECT *
, результатом запроса является полный элемент JSON. Дополнительные сведения о синтаксисе SELECT см. В разделе Оператор SELECT.
ВЫБРАТЬ *
ИЗ семей f
ГДЕ f.id = "AndersenFamily"
Результаты запроса:
[{
"id": "Семья Андерсена",
"lastName": "Андерсен",
"родители": [
{"firstName": "Томас"},
{"firstName": "Мэри Кей"}
],
"дети": [
{
"firstName": "Генриетта Таулов", "пол": "женский", "класс": 5,
"домашние животные": [{"givenName": "Пушистый"}]
}
],
"address": {"state": "WA", "county": "King", "city": "Сиэтл"},
"creationDate": 1431620472,
"isRegistered": true
}]
Следующий запрос переформатирует вывод JSON в другую форму. Запрос проецирует новый объект JSON Family
с двумя выбранными полями, Name
и City
, когда адрес city совпадает с государством. «NY, NY» соответствует этому случаю.
SELECT {"Имя": f.id, "Город": f.address.city} как Семья
ИЗ семей f
ГДЕ f.address.city = f.address.state
Результаты запроса:
[{
"Семья": {
"Имя": "WakefieldFamily",
«Город»: «Нью-Йорк»
}
}]
Следующий запрос возвращает все заданные имена детей в семье, чей идентификатор
совпадает с WakefieldFamily
, отсортированные по городам.
ВЫБРАТЬ c.givenName
ИЗ семей f
ПРИСОЕДИНЯЙТЕСЬ c IN f. Дети
ГДЕ f.id = 'WakefieldFamily'
ЗАКАЗ ПО f.address.city ASC
Результаты:
[
{"givenName": "Джесси"},
{"givenName": "Лиза"}
]
Замечания
В предыдущих примерах показаны несколько аспектов языка запросов Cosmos DB:
Поскольку SQL API работает со значениями JSON, он работает с объектами в форме дерева, а не с строками и столбцами. Вы можете ссылаться на узлы дерева на любой произвольной глубине, например,
Node1.Node2.Node3… ..Nodem
, аналогично двухчастной ссылке.
в ANSI SQL. Поскольку язык запросов работает с данными без схемы, система типов должна быть привязана динамически. Одно и то же выражение может давать разные типы для разных элементов. Результатом запроса является допустимое значение JSON, но его соответствие фиксированной схеме не гарантируется.
Azure Cosmos DB поддерживает только элементы строго JSON.Система типов и выражения могут иметь дело только с типами JSON. Дополнительные сведения см. В спецификации JSON.
Контейнер Cosmos — это коллекция элементов JSON без схемы. Отношения внутри и между элементами контейнера неявно фиксируются включением, а не отношениями первичного и внешнего ключей. Эта функция важна для соединений внутри элемента, описанных в разделе Соединения в Azure Cosmos DB.
Следующие шаги
.