Zum Hauptinhalt springen

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​

  1. Beginnen Sie mit sinnvollen Seitengrößen: 20–50 Elemente für UI-Listen, bis zu 100 für Hintergrundverarbeitung
  2. Verwenden Sie hasNextPage: Prüfen Sie es, bevor Sie weitere Anfragen stellen
  3. Bewahren Sie Cursor auf: Speichern Sie endCursor für „Mehr laden"-Funktionalität
  4. 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​

PraxisNutzen
Paginierung verwendenVerhindert große Antwort-Payloads
Nur benötigte Felder abfragenReduziert die Antwortgröße
Variablen verwendenSicherheit, Caching, Lesbarkeit
Aliase verwendenMehrere Queries in einer Anfrage
Fragmente verwendenDRY, wartbare Feldauswahlen
StapeloperationenWeniger Netzwerkanfragen
Spezifische FilterSchnellere Query-Ausführung
N+1 vermeidenWeniger Datenbankabfragen