A Data API Builder (DAB) GraphQL-végpontjai lehetővé teszik az adatok pontos lekérdezését és módosítását.
Minden lekérdezés pontosan meghatározza, hogy milyen mezőkre van szüksége, és támogatja a szűrési, rendezési és lapozási eredmények argumentumait.
Alapértelmezés szerint a DAB a GraphQL-végpontját a következő helyen tárolja:
https://{base_url}/graphql
A konfigurációval közzétett entitások automatikusan bekerülnek a GraphQL-sémába.
Ha például vannak books és authors entitások, mindkettő gyökérmezőként jelenik meg a sémában.
Megjegyzés:
A séma és az automatikus kiegészítési mezők megismeréséhez használjon bármilyen modern GraphQL-ügyfelet vagy IDE-t (például az Apollót, az Álmatlanságot vagy a Visual Studio Code GraphQL-bővítményt).
A Data API Builderben támogatott kulcsszavak
| Fogalom |
GraphQL |
Alkalmazás célja |
| Projection |
Elemek |
Adja meg, hogy mely mezőket adja vissza |
| Filtering |
szűrő |
Sorok korlátozása feltétel szerint |
| Rendezés |
orderBy |
Rendezési sorrend meghatározása |
| Oldalméret |
első |
Az elemek korlátozása oldalanként |
| Folytatás |
után |
Folytatás az utolsó oldalról |
Alapszintű struktúra
Minden GraphQL-lekérdezés egy entitást jelképező gyökérmezővel kezdődik.
Minden GraphQL-kérés a POST használatával a /graphql végpontra irányul, és a lekérdezést tartalmazó JSON-törzset küld.
{
books {
items {
id
title
year
pages
}
}
}
A válasz egy olyan JSON-objektum, amelynek alakzata megegyezik a kijelölési csoportéval.
A lapozás és a hiba részletei csak akkor jelennek meg, ha alkalmazhatók.
Megjegyzés:
Alapértelmezés szerint a DAB lekérdezésenként legfeljebb 100 elemet ad vissza, kivéve, ha másként van konfigurálva (runtime.pagination.default-page-size).
POST https://localhost:5001/graphql
Content-Type: application/json
{
"query": "{ books { items { id title year pages } } }"
}
Siker:
{
"data": {
"books": {
"items": [
{ "id": 1, "title": "Dune", "year": 1965, "pages": 412 },
{ "id": 2, "title": "Foundation", "year": 1951, "pages": 255 }
]
}
}
}
Siker az oldalkezeléssel:
{
"data": {
"books": {
"items": [
{ "id": 1, "title": "Dune", "year": 1965, "pages": 412 },
{ "id": 2, "title": "Foundation", "year": 1951, "pages": 255 }
],
"hasNextPage": true,
"endCursor": "eyJpZCI6Mn0="
}
}
}
Hiba:
{
"errors": [
{
"message": "Could not find item with the given key.",
"locations": [{ "line": 1, "column": 3 }],
"path": ["book_by_pk"]
}
]
}
curl -X POST "https://localhost:5001/graphql" \
-H "Content-Type: application/json" \
-d '{"query": "{ books { items { id title year pages } } }"}'
A következő modellosztályok deszerializálják a DAB GraphQL-válaszokat:
using System.Text.Json.Serialization;
public class GraphQLRequest
{
[JsonPropertyName("query")]
public string Query { get; set; } = string.Empty;
[JsonPropertyName("variables")]
public object? Variables { get; set; }
}
public class GraphQLResponse<T>
{
[JsonPropertyName("data")]
public T? Data { get; set; }
[JsonPropertyName("errors")]
public List<GraphQLError>? Errors { get; set; }
[JsonIgnore]
public bool IsSuccess => Errors is null || Errors.Count == 0;
}
public class GraphQLError
{
[JsonPropertyName("message")]
public string Message { get; set; } = string.Empty;
[JsonPropertyName("path")]
public List<string>? Path { get; set; }
}
public class BooksResponse
{
[JsonPropertyName("books")]
public BooksResult? Books { get; set; }
}
public class BooksResult
{
[JsonPropertyName("items")]
public List<Book>? Items { get; set; }
[JsonPropertyName("hasNextPage")]
public bool HasNextPage { get; set; }
[JsonPropertyName("endCursor")]
public string? EndCursor { get; set; }
}
public class Book
{
[JsonPropertyName("id")]
public int Id { get; set; }
[JsonPropertyName("title")]
public string Title { get; set; } = string.Empty;
[JsonPropertyName("year")]
public int? Year { get; set; }
[JsonPropertyName("pages")]
public int? Pages { get; set; }
}
Hívja meg az API-t, és deszerializálja a választ:
public async Task<List<Book>> GetBooksAsync()
{
var request = new GraphQLRequest
{
Query = "{ books { items { id title year pages } } }"
};
var response = await httpClient.PostAsJsonAsync("graphql", request);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<GraphQLResponse<BooksResponse>>();
if (result?.Errors?.Count > 0)
{
throw new Exception(result.Errors[0].Message);
}
return result?.Data?.Books?.Items ?? [];
}
A következő adat osztályok modellezik a DAB GraphQL-válaszokat:
from dataclasses import dataclass, field
import requests
@dataclass
class Book:
id: int
title: str
year: int | None = None
pages: int | None = None
@dataclass
class GraphQLError:
message: str
path: list[str] | None = None
@dataclass
class BooksResult:
items: list[Book] = field(default_factory=list)
has_next_page: bool = False
end_cursor: str | None = None
@dataclass
class GraphQLResponse:
data: dict | None = None
errors: list[GraphQLError] | None = None
@property
def is_success(self) -> bool:
return self.errors is None or len(self.errors) == 0
Hívja meg az API-t, és elemezje a választ:
def get_books(base_url: str) -> list[Book]:
query = "{ books { items { id title year pages } } }"
response = requests.post(
f"{base_url}/graphql",
json={"query": query}
)
response.raise_for_status()
data = response.json()
if "errors" in data and data["errors"]:
raise Exception(data["errors"][0]["message"])
items = data.get("data", {}).get("books", {}).get("items", [])
return [Book(**item) for item in items]
A következő függvény meghívja a GraphQL API-t:
async function getBooks(baseUrl) {
const query = "{ books { items { id title year pages } } }";
const response = await fetch(`${baseUrl}/graphql`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query }),
});
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const result = await response.json();
if (result.errors?.length > 0) {
throw new Error(result.errors[0].message);
}
return result.data?.books?.items ?? [];
}
Példahasználat:
const books = await getBooks("https://localhost:5001");
console.log(`Fetched ${books.length} books from the API.`);
Lekérdezéstípusok
Mindegyik entitás két szabványos gyökér lekérdezést támogat:
| Lekérdezés |
Leírás |
entity_by_pk |
Egy rekordot ad vissza az elsődleges kulcsa alapján |
entities |
A szűrőknek megfelelő rekordok listáját adja vissza |
Példa egy rekord visszaadására:
{
book_by_pk(id: 1010) {
title
year
}
}
Több értéket visszaadó példa:
{
books {
items {
id
title
}
}
}
Eredmények szűrése
filter Az argumentum használatával korlátozhatja, hogy mely rekordokat adja vissza a rendszer.
{
books(filter: { title: { contains: "Foundation" } }) {
items { id title }
}
}
Ez a lekérdezés az összes olyan könyvet visszaadja, amelynek a címe "Foundation" (Alapozás) címet tartalmazza.
A szűrők kombinálhatják a logikai operátorokkal való összehasonlítást:
{
authors(filter: {
or: [
{ first_name: { eq: "Isaac" } }
{ last_name: { eq: "Asimov" } }
]
}) {
items { first_name last_name }
}
}
Tekintse meg a támogatott operátorok szűrőargumentum-hivatkozását, például eq: , neq, ltlteés isNull.
Találatok rendezése
Az orderBy argumentum határozza meg a rekordok rendezésének módját.
{
books(orderBy: { year: DESC, title: ASC }) {
items { id title year }
}
}
Ez visszaadja a year szerint csökkenő sorrendben, majd a title alapján rendezett könyveket.
További információkért lásd a orderBy argumentum dokumentációját.
Eredmények korlátozása
Az first argumentum korlátozza, hogy egy kérelem hány rekordot ad vissza.
{
books(first: 5) {
items { id title }
}
}
Ez az első öt könyvet adja vissza, alapértelmezés szerint az elsődleges kulcs szerint rendezve.
A konfigurált maximális oldalméretet is kérheti first: -1 .
További információ az első argumentumhivatkozásban.
Folyamatos eredmények
A következő lap beolvasásához használja az after argumentumot az előző lekérdezés kurzorával.
{
books(first: 5, after: "eyJpZCI6NX0=") {
items { id title }
}
}
A after token jelzi, hogy hol végződött az előző oldal.
További információt az argumentum utáni hivatkozásban talál.
Mezőválasztás (projekció)
A GraphQL-ben pontosan kiválaszthatja, hogy mely mezők jelenjenek meg a válaszban.
Nincs ilyen SELECT * helyettesítő karakter. Csak azt kérje, amire szüksége van.
{
books {
items { id title price }
}
}
Aliasokkal is átnevezheti a mezőket a válaszban:
{
books {
items {
bookTitle: title
cost: price
}
}
}
Részletekért lásd a mezővetítési referenciát .
Adatok módosítása
A GraphQL-mutációk lehetővé teszik rekordok létrehozását, frissítését és törlését az entitásengedélyek függvényében.
| Mutáció |
Action |
createEntity |
Új elem létrehozása |
updateEntity |
Meglévő elem frissítése |
deleteEntity |
Elem eltávolítása |
Megjegyzés:
Az _by_pk utótag csak lekérdezésekre vonatkozik (például book_by_pk). A mutációnevek nem tartalmazzák ezt az utótagot – használja a updateBook és a deleteBook kifejezéseket, ne pedig a updateBook_by_pk vagy deleteBook_by_pk kifejezéseket.
Fontos
A GraphQL-mutációkhoz aktív adatbázis-kapcsolatkészlet szükséges. Ha a kapcsolati sztring beállítja Pooling=False vagy MultipleActiveResultSets=False, a mutációk a hibával Implicit distributed transactions have not been enabled meghiúsulnak. Állítsa be Pooling=True és MultipleActiveResultSets=True (SQL Server) vagy az adatbázis-szolgáltató megfelelőjeként.
Jótanács
A GraphQL-ben közzétett tárolt eljárások esetében a DAB előtagja az entitás nevét a következővel executejelöli: . Például egy GetBookById nevű tárolt eljárás entitás a sémában executeGetBookById lesz. További információ: tárolt eljárások.
Új rekord létrehozása
create Új elem hozzáadásához használjon mutációt.
POST https://localhost:5001/graphql
Content-Type: application/json
{
"query": "mutation { createBook(item: { id: 2000, title: \"Leviathan Wakes\", year: 2011, pages: 577 }) { id title year pages } }"
}
curl -X POST "https://localhost:5001/graphql" \
-H "Content-Type: application/json" \
-d '{"query": "mutation { createBook(item: { id: 2000, title: \"Leviathan Wakes\", year: 2011, pages: 577 }) { id title year pages } }"}'
var request = new GraphQLRequest
{
Query = @"
mutation CreateBook($item: CreateBookInput!) {
createBook(item: $item) { id title year pages }
}",
Variables = new
{
item = new { id = 2000, title = "Leviathan Wakes", year = 2011, pages = 577 }
}
};
var response = await httpClient.PostAsJsonAsync("graphql", request);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<GraphQLResponse<CreateBookResponse>>();
if (result?.Errors?.Count > 0)
{
throw new Exception(result.Errors[0].Message);
}
query = """
mutation CreateBook($item: CreateBookInput!) {
createBook(item: $item) { id title year pages }
}
"""
variables = {
"item": {"id": 2000, "title": "Leviathan Wakes", "year": 2011, "pages": 577}
}
response = requests.post(
f"{base_url}/graphql",
json={"query": query, "variables": variables}
)
response.raise_for_status()
data = response.json()
if "errors" in data and data["errors"]:
raise Exception(data["errors"][0]["message"])
const query = `
mutation CreateBook($item: CreateBookInput!) {
createBook(item: $item) { id title year pages }
}
`;
const variables = {
item: { id: 2000, title: "Leviathan Wakes", year: 2011, pages: 577 },
};
const response = await fetch(`${baseUrl}/graphql`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query, variables }),
});
const result = await response.json();
if (result.errors?.length > 0) {
throw new Error(result.errors[0].message);
}
Egy létező rekord frissítése
update Egy meglévő elem adott mezőinek módosításához használjon mutációt.
POST https://localhost:5001/graphql
Content-Type: application/json
{
"query": "mutation { updateBook(id: 2000, item: { title: \"Leviathan Wakes\", year: 2011, pages: 577 }) { id title year pages } }"
}
curl -X POST "https://localhost:5001/graphql" \
-H "Content-Type: application/json" \
-d '{"query": "mutation { updateBook(id: 2000, item: { title: \"Leviathan Wakes\", year: 2011, pages: 577 }) { id title year pages } }"}'
var request = new GraphQLRequest
{
Query = @"
mutation UpdateBook($id: Int!, $item: UpdateBookInput!) {
updateBook(id: $id, item: $item) { id title year pages }
}",
Variables = new
{
id = 2000,
item = new { title = "Leviathan Wakes", year = 2011, pages = 577 }
}
};
var response = await httpClient.PostAsJsonAsync("graphql", request);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<GraphQLResponse<UpdateBookResponse>>();
if (result?.Errors?.Count > 0)
{
throw new Exception(result.Errors[0].Message);
}
query = """
mutation UpdateBook($id: Int!, $item: UpdateBookInput!) {
updateBook(id: $id, item: $item) { id title year pages }
}
"""
variables = {
"id": 2000,
"item": {"title": "Leviathan Wakes", "year": 2011, "pages": 577}
}
response = requests.post(
f"{base_url}/graphql",
json={"query": query, "variables": variables}
)
response.raise_for_status()
data = response.json()
if "errors" in data and data["errors"]:
raise Exception(data["errors"][0]["message"])
const query = `
mutation UpdateBook($id: Int!, $item: UpdateBookInput!) {
updateBook(id: $id, item: $item) { id title year pages }
}
`;
const variables = {
id: 2000,
item: { title: "Leviathan Wakes", year: 2011, pages: 577 },
};
const response = await fetch(`${baseUrl}/graphql`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query, variables }),
});
const result = await response.json();
if (result.errors?.length > 0) {
throw new Error(result.errors[0].message);
}
Rekord törlése
delete Egy elem elsődleges kulcs szerinti eltávolításához használjon mutációt.
POST https://localhost:5001/graphql
Content-Type: application/json
{
"query": "mutation { deleteBook(id: 2000) { id title } }"
}
curl -X POST "https://localhost:5001/graphql" \
-H "Content-Type: application/json" \
-d '{"query": "mutation { deleteBook(id: 2000) { id title } }"}'
var request = new GraphQLRequest
{
Query = @"
mutation DeleteBook($id: Int!) {
deleteBook(id: $id) { id title }
}",
Variables = new { id = 2000 }
};
var response = await httpClient.PostAsJsonAsync("graphql", request);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<GraphQLResponse<DeleteBookResponse>>();
if (result?.Errors?.Count > 0)
{
throw new Exception(result.Errors[0].Message);
}
query = """
mutation DeleteBook($id: Int!) {
deleteBook(id: $id) { id title }
}
"""
variables = {"id": 2000}
response = requests.post(
f"{base_url}/graphql",
json={"query": query, "variables": variables}
)
response.raise_for_status()
data = response.json()
if "errors" in data and data["errors"]:
raise Exception(data["errors"][0]["message"])
const query = `
mutation DeleteBook($id: Int!) {
deleteBook(id: $id) { id title }
}
`;
const variables = { id: 2000 };
const response = await fetch(`${baseUrl}/graphql`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query, variables }),
});
const result = await response.json();
if (result.errors?.length > 0) {
throw new Error(result.errors[0].message);
}