Best Practices
Dieses Kapitel enthält Best Practices für das Schreiben effizienter und wartbarer GraphQL-Queries und -Mutationen.
Paginierung
Verwenden Sie stets Paginierung für Queries, die große Ergebnismengen zurückgeben können.
Cursor-basierte Paginierung
query getEnergyMeters($first: Int!, $after: String) {
runtime {
industryEnergyEnergyMeter(first: $first, after: $after) {
pageInfo {
endCursor
hasNextPage
}
totalCount
items {
rtId
name
}
}
}
}
Paginierungsstrategie
- Beginnen Sie mit sinnvollen Seitengrößen: 20–50 Elemente für UI-Listen, bis zu 100 für Hintergrundverarbeitung
- Verwenden Sie
hasNextPage: Prüfen Sie es, bevor Sie weitere Anfragen stellen - Bewahren Sie Cursor auf: Speichern Sie
endCursorfür „Mehr laden"-Funktionalität - Berücksichtigen Sie
totalCount: Verwenden Sie es sparsam, da es eine vollständige Count-Query erfordern kann
Nur benötigte Felder abfragen
Fordern Sie nur die Felder an, die Sie tatsächlich benötigen. Dies reduziert die Antwortgröße und verbessert die Performance.
# Good - only request needed fields
query {
runtime {
industryEnergyEnergyMeter(first: 10) {
items {
rtId
name
state
}
}
}
}
# Avoid - requesting all fields when only a few are needed
query {
runtime {
industryEnergyEnergyMeter(first: 10) {
items {
rtId
ckTypeId
name
description
voltage
ampere
power
state
# ... many more fields
}
}
}
}
Variablen verwenden
Verwenden Sie stets GraphQL-Variablen anstelle von String-Interpolation. Dies verbessert Sicherheit, Caching und Lesbarkeit.
# Good - using variables
query getEnergyMeter($rtId: OctoObjectId!) {
runtime {
industryEnergyEnergyMeter(rtId: $rtId) {
items {
rtId
name
}
}
}
}
# Avoid - hardcoded values
query {
runtime {
industryEnergyEnergyMeter(rtId: "65dc6d24cc529cdc46c84fcc") {
items {
rtId
name
}
}
}
}
Aliase
Verwenden Sie Aliase, wenn Sie dasselbe Feld mit unterschiedlichen Argumenten in einer einzigen Anfrage abfragen müssen:
query {
runtime {
activeMeters: industryEnergyEnergyMeter(
fieldFilter: [{ attributePath: "state", operator: EQUALS, comparisonValue: "ON" }]
) {
totalCount
}
inactiveMeters: industryEnergyEnergyMeter(
fieldFilter: [{ attributePath: "state", operator: EQUALS, comparisonValue: "OFF" }]
) {
totalCount
}
}
}
Ergebnis:
{
"data": {
"runtime": {
"activeMeters": { "totalCount": 15 },
"inactiveMeters": { "totalCount": 8 }
}
}
}
Fragmente
Verwenden Sie Fragmente, um Feldauswahlen über mehrere Queries hinweg wiederzuverwenden:
fragment EnergyMeterFields on IndustryEnergyEnergyMeter {
rtId
ckTypeId
name
voltage
}
query getEnergyMeters {
runtime {
industryEnergyEnergyMeter(first: 10) {
items {
...EnergyMeterFields
}
}
}
}
query getEnergyMeterById($rtId: OctoObjectId!) {
runtime {
industryEnergyEnergyMeter(rtId: $rtId) {
items {
...EnergyMeterFields
description
ampere
power
}
}
}
}
Stapeloperationen
Wenn Sie mehrere Entitäten erstellen oder aktualisieren, verwenden Sie Stapeloperationen anstelle mehrerer Anfragen:
# Good - single request with multiple entities
mutation createMultipleMeters($entities: [IndustryEnergyEnergyMeterInput]!) {
runtime {
industryEnergyEnergyMeters {
create(entities: $entities) {
rtId
name
}
}
}
}
# Avoid - multiple separate requests
# Request 1: create entity A
# Request 2: create entity B
# Request 3: create entity C
Filteroptimierung
Spezifische Filter verwenden
Spezifischere Filter führen zu schnelleren Queries:
# Good - specific filter
query {
runtime {
industryEnergyEnergyMeter(
fieldFilter: [
{ attributePath: "state", operator: EQUALS, comparisonValue: "ON" },
{ attributePath: "voltage", operator: GREATER_THAN, comparisonValue: 220 }
]
) {
items { rtId name }
}
}
}
# Less efficient - broad filter with client-side filtering
query {
runtime {
industryEnergyEnergyMeter {
items { rtId name voltage }
}
}
}
# Then filter in code...
rtId verwenden, wenn verfügbar
Direkte rtId-Abfragen sind am schnellsten:
# Fastest - direct ID lookup
query {
runtime {
industryEnergyEnergyMeter(rtId: "65dc6d24cc529cdc46c84fcc") {
items { rtId name }
}
}
}
N+1-Queries vermeiden
Verwenden Sie Assoziationen innerhalb einer einzigen Query, anstatt separate Anfragen zu stellen:
# Good - single query with associations
query {
runtime {
systemCommunicationDataFlow(first: 10) {
items {
rtId
name
children {
systemCommunicationPipeline {
items {
rtId
name
}
}
}
}
}
}
}
# Avoid - N+1 pattern
# Query 1: Get all pipelines
# Query 2-N: For each pipeline, get children
Namenskonventionen
Verwenden Sie beschreibende Namen für Operationen:
# Good - descriptive operation names
query getActiveEnergyMetersByLocation { ... }
mutation updateEnergyMeterState { ... }
# Avoid - generic or missing names
query { ... }
mutation doUpdate { ... }
Fehlerbehandlung
Behandeln Sie Fehler stets angemessen. Details finden Sie unter Fehlerbehandlung.
const response = await client.query({ query: GET_METERS });
if (response.errors) {
// Handle errors
}
if (response.data) {
// Process data
}
Zusammenfassung
| Praxis | Nutzen |
|---|---|
| Paginierung verwenden | Verhindert große Antwort-Payloads |
| Nur benötigte Felder abfragen | Reduziert die Antwortgröße |
| Variablen verwenden | Sicherheit, Caching, Lesbarkeit |
| Aliase verwenden | Mehrere Queries in einer Anfrage |
| Fragmente verwenden | DRY, wartbare Feldauswahlen |
| Stapeloperationen | Weniger Netzwerkanfragen |
| Spezifische Filter | Schnellere Query-Ausführung |
| N+1 vermeiden | Weniger Datenbankabfragen |