{ }
type
GraphQL · Magento · OpenSearch · Suche · Performance
OpenSearch und Magento GraphQL
Wie Suche wirklich zusammenspielt

Wenn eine Magento-GraphQL-Produktsuche langsam ist, liegt das Problem selten in der GraphQL-Schicht. Es liegt fast immer darin, wie Suchanfragen durch Resolver an OpenSearch weitergeleitet werden — und ob Indexierung, Filter-Mapping und Sortierung korrekt konfiguriert sind.

17 Min. Lesezeit OpenSearch · Indexierung · Filter-Mapping · Resolver Magento 2.4 · OpenSearch 2.x

1. Die Sucharchitektur in Magento: vom GraphQL-Request bis OpenSearch

Wenn ein Headless-Frontend eine GraphQL-Produktsuche absetzt (products(search: "...")), durchläuft die Anfrage mehrere Schichten, bevor das Ergebnis zurückkommt. Der Resolver empfängt die Argumente, erstellt ein SearchCriteria-Objekt und übergibt es an den Produkt-Repository. Sobald ein search-Argument vorhanden ist, leitet Magento die Anfrage automatisch an den Suchadapter weiter — in Magento 2.4 standardmäßig OpenSearch. Dieser Adapter übersetzt das SearchCriteria-Objekt in eine OpenSearch-Query, sendet sie an den OpenSearch-Cluster und gibt die Ergebnis-IDs zurück.

Die zurückgegebenen IDs werden danach in einer zweiten Datenbankabfrage verwendet, um die vollständigen Produktdaten zu laden — Attribute, die nicht im OpenSearch-Index sind, werden aus der Datenbank nachgeladen. Das ist ein wichtiger Punkt: OpenSearch gibt nicht die vollständigen Produktdaten zurück, sondern primär IDs und Relevanz-Scores. Magento kombiniert OpenSearch-Ergebnisse und Datenbankdaten in der finalen Response. Diese Architektur ist transparent für den GraphQL-Client, aber für Performance-Optimierungen muss man beide Schichten kennen.

Der Suchadapter ist dabei auswechselbar. Magento abstrahiert den konkreten Suchdienst hinter Interfaces, sodass ein Wechsel von OpenSearch zu einem anderen Suchdienst theoretisch ohne Änderungen an den Resolvern möglich ist. In der Praxis wird dieses Versprechen durch Adapter-spezifische Konfigurationen eingeschränkt — aber das Grundprinzip der Schichtentrennung ist solide.

2. Indexierung: Was OpenSearch über Produkte weiß

OpenSearch kennt nur, was Magento in den Index geschrieben hat. Der Catalog-Index enthält für jedes Produkt eine Reihe von Standardfeldern: SKU, Name, Beschreibung, Preis, Status, Sichtbarkeit und alle konfigurierten searchable und filterable Attribute. Nicht im Index sind: komplexe EAV-Beziehungen, Custom Options, konfigurierbare Varianten-Details und alle Attribute, die in der Admin-Konfiguration nicht als Used in Layered Navigation oder Searchable markiert sind.

Das hat direkte Auswirkungen auf GraphQL-Filter. Ein Filter auf ein Attribut, das nicht im Index ist, zwingt Magento zurück auf einen Datenbank-Fallback — und dieser Fallback verliert alle Vorteile von OpenSearch: Relevanz-Scoring, schnelle Volltext-Suche und Aggregations für Facetten-Filter. Deshalb ist die Indexierungskonfiguration nicht nur eine Admin-Einstellung, sondern eine architektonische Entscheidung, die direkt die Performance von GraphQL-Suchabfragen beeinflusst.

3. Der Produkt-Resolver: Wie er zwischen DB und OpenSearch entscheidet

Magento's interner Produkt-Resolver prüft, ob die eingehende Query ein search- oder ein filter-Argument enthält. Bei einem search-Argument wird zwingend der Suchadapter (OpenSearch) verwendet. Bei einem reinen filter-Argument hängt es davon ab, ob die Filter auf indexierten Attributen basieren oder nicht. Wenn alle Filter auf filterable-Attributen basieren, kann OpenSearch die Filter-Abfrage ebenfalls übernehmen — mit erheblichen Performance-Vorteilen gegenüber DB-Queries.

Das Switching-Verhalten ist nicht immer transparent. In Magento-Logs sieht man nicht direkt, welcher Pfad genommen wurde — man muss das an der Query-Struktur und den Response-Zeiten ableiten. Ein einfacher Diagnosetest: dieselbe Query mit search: "" (leerer Suchstring) und ohne search-Argument absenden und die Antwortzeiten vergleichen. Wenn der Unterschied erheblich ist, läuft einer der beiden Pfade über die Datenbank statt über OpenSearch.


# Query type 1: full-text search — always uses OpenSearch
query SearchProducts {
  products(
    search: "running shoes"
    filter: {
      price: { from: "30.00", to: "200.00" }
    }
    pageSize: 24
    currentPage: 1
    sort: { relevance: DESC }
  ) {
    total_count
    aggregations {
      attribute_code
      label
      count
      options {
        label
        value
        count
      }
    }
    items {
      sku
      name
      url_key
    }
  }
}

# Query type 2: filter-only — may or may not use OpenSearch
# depends on whether filter attributes are indexed
query FilterProducts {
  products(
    filter: {
      category_id: { eq: "5" }
      price: { from: "50.00", to: "150.00" }
    }
    pageSize: 24
  ) {
    total_count
    items {
      sku
      name
    }
  }
}

4. Filter-Mapping: GraphQL-Argumente in OpenSearch-Queries übersetzen

Wenn ein GraphQL-Filter an OpenSearch weitergeleitet wird, übersetzt Magento's Suchadapter das SearchCriteria-Objekt in eine OpenSearch-Query DSL. Einfache Gleichheitsfilter werden zu term-Queries, Bereichsfilter zu range-Queries, und Volltext-Suchen zu multi_match- oder query_string-Queries. Diese Übersetzung ist automatisch — aber nur, wenn das gefilterte Attribut korrekt im OpenSearch-Mapping konfiguriert ist.

Das OpenSearch-Feldmapping definiert, wie Magento ein Produktattribut im Index speichert. Textfelder können als text (für Volltext-Suche mit Tokenisierung) oder als keyword (für exakte Filter-Abfragen) gespeichert werden — oft beides gleichzeitig als Multi-Field. Filterbare Attribute werden typischerweise als keyword gespeichert, damit sie für präzise term-Queries verwendbar sind. Wenn ein Attribut fehlt oder falsch gemappt ist, liefert der OpenSearch-Filter kein Ergebnis — ohne Fehlermeldung, nur mit leerem Ergebnissatz.

5. Suchanfragen analysieren: Queries debuggen und optimieren

Das effektivste Werkzeug zum Debuggen von Magento-OpenSearch-Anfragen ist das OpenSearch-Query-Logging. Über die OpenSearch-Admin-Oberfläche oder direkt über die REST-API lassen sich die tatsächlichen Query-DSL-Objekte einsehen, die Magento an OpenSearch sendet. Diese Information zeigt, welche Filter übersetzt wurden, welche Relevanz-Boosts angewendet werden und ob die Query die erwarteten Treffer erzeugt.

Ein weiteres wichtiges Diagnose-Tool ist Magento's eigenes bin/magento indexer:status. Wenn der Catalog-Index nicht aktuell ist, liefert OpenSearch veraltete oder fehlende Produkte — ohne Fehlermeldung in der GraphQL-Response. Performance-Probleme, die sich durch langsame Response-Zeiten trotz korrekter OpenSearch-Konfiguration äußern, liegen häufig in der zweiten Phase: dem Nachladen von Produkt-Details aus der Datenbank für Attribute, die nicht im Index sind.


# Debug query: check if aggregations (facets) are returned correctly
# Aggregations are only available when using OpenSearch
query DebugSearchWithAggregations {
  products(
    search: "jacket"
    filter: {
      category_id: { eq: "12" }
    }
    pageSize: 1
    currentPage: 1
  ) {
    total_count
    # If aggregations are empty or missing, OpenSearch is not being used
    # or the indexed attributes are not configured as filterable
    aggregations {
      attribute_code
      label
      count
      options {
        label
        value
        count
      }
    }
    # page_info helps verify pagination works correctly with OpenSearch
    page_info {
      current_page
      page_size
      total_pages
    }
    items {
      sku
    }
  }
}

# Expected: aggregations contains price, color, size, etc.
# Missing aggregations = OpenSearch not engaged or attribute not indexed

6. Aggregations: Wie Facetten-Filter aus OpenSearch kommen

Das aggregations-Feld in Magento's GraphQL-Schema ist eine der wichtigsten Features der OpenSearch-Integration. Es liefert für jedes filterbare Attribut eine Liste von verfügbaren Werten mit der Anzahl der Treffer pro Wert — das ist die Grundlage für dynamische Facetten-Filter im Headless-Frontend. Diese Daten kommen direkt aus OpenSearch's Aggregations-Funktion und sind ein einziges Query-Ergebnis — kein separater API-Call pro Filterattribut.

Aggregations funktionieren nur, wenn OpenSearch für die Anfrage verwendet wird. Bei einem reinen Datenbank-Fallback gibt das aggregations-Feld ein leeres Array zurück. Das ist einer der häufigsten Fehler beim Aufbau von Headless-Frontends: Das Frontend erwartet Aggregationen für Facetten-Filter, aber weil ein Filter auf einem nicht-indizierten Attribut den OpenSearch-Pfad umgeht, kommen keine Aggregationen zurück. Die Lösung ist immer dieselbe: Das Filterattribut in der Admin-Konfiguration als Used in Layered Navigation aktivieren und den Index neu aufbauen.

7. DB-Suche vs. OpenSearch: Was wirklich langsamer ist und warum

Kriterium Datenbank-Suche OpenSearch Vorteil
Volltext-Suche LIKE-Query, langsam Invertierter Index, schnell OpenSearch: 10-100x schneller
Facetten-Aggregationen Separate COUNT-Queries pro Attribut Eine Aggregation, alle Werte OpenSearch: O(1) statt O(n)
EAV-Filter JOIN über mehrere Tabellen Denormalisiert im Index OpenSearch: keine Joins nötig
Relevanz-Ranking Nicht vorhanden TF/IDF und BM25 Bessere Suchergebnisse
Skalierbarkeit Lineare Degradierung bei großen Katalogen Horizontale Skalierung OpenSearch: Cluster skalierbar

Die Tabelle macht deutlich: OpenSearch ist für alle Suchszenarien in Magento deutlich überlegen. Das einzige Szenario, in dem die Datenbank noch eine Rolle spielt, ist das Nachladen von Produkt-Detaildaten, die nicht im Index sind. Genau deshalb ist die Indexierungsstrategie so wichtig: Je mehr relevante Produktdaten im Index sind, desto weniger DB-Abfragen sind für eine vollständige GraphQL-Response nötig.

8. Eigene Attribute für die Suche konfigurieren

Eigene Produktattribute aus Custom Modules sind standardmäßig nicht im OpenSearch-Index enthalten. Damit ein benutzerdefiniertes Attribut in GraphQL-Filtern verwendet werden kann und Aggregationen liefert, müssen drei Konfigurationsschritte durchgeführt werden. Erstens: Das Attribut muss in der Admin-Oberfläche als Used in Layered Navigation aktiviert werden (für Facetten-Filter) und/oder als Use in Search (für Volltext-Suche). Zweitens: Das Attribut muss zur Schema-Graphqls-Datei des Moduls hinzugefügt werden, damit es im GraphQL-Filter-Input verfügbar ist. Drittens: Der Catalog-Index muss neu aufgebaut werden (bin/magento indexer:reindex catalogsearch_fulltext).

Ein häufig übersehener vierter Schritt: Das OpenSearch-Feldmapping muss überprüft werden. Wenn ein Attribut mit einem ungeeigneten Datentyp im Index gespeichert wird — etwa ein numerisches Attribut als String —, funktionieren Bereichsfilter nicht korrekt. Das Mapping kann über die OpenSearch-REST-API eingesehen werden (GET /magento2_product_1/_mapping) und muss gegebenenfalls nach einer Index-Rekonfiguration neu aufgebaut werden.

9. Typische Fehlerbilder: Wenn Suche nicht das zurückgibt, was erwartet wird

Das häufigste Fehlerbild: Eine Volltext-Suche gibt zu viele oder zu wenige Ergebnisse zurück. Der Grund liegt fast immer in der Gewichtung der Suchfelder im OpenSearch-Index. Magento konfiguriert standard Gewichtungen für Name, Beschreibung und SKU — aber Custom Attributes, die als Suchfelder konfiguriert sind, erhalten oft zu hohe oder zu niedrige Gewichtungen. Das Ergebnis sind irrelevante Treffer auf den ersten Positionen oder gewünschte Produkte, die gar nicht erscheinen.

Ein zweites Fehlerbild: Kategoriefilter liefert falsche Ergebnisse. In Magento wird die Kategorienzugehörigkeit im Index als Array von Kategorie-IDs gespeichert — inklusive aller Elternkategorien. Wenn ein GraphQL-Filter eine Kategorie-ID verwendet, die im Index nicht in dieser Form vorhanden ist (etwa weil der Category-Index veraltet ist), gibt die Suche leere Ergebnisse zurück. Der Fix ist simpel: bin/magento indexer:reindex catalog_category_product und danach catalogsearch_fulltext.


# Diagnostic query: verify custom attribute is indexed and filterable
query CheckCustomAttributeFilter {
  products(
    filter: {
      # custom_material must be configured as:
      # - "Used in Layered Navigation: Filterable"
      # - "Use in Search: Yes" (if full-text searchable)
      custom_material: { eq: "cotton" }
    }
    pageSize: 5
  ) {
    total_count
    aggregations {
      attribute_code
      label
      # custom_material should appear here if correctly indexed
    }
    items {
      sku
      name
      # custom_material field must be added to schema.graphqls
      # and ProductInterface extension to appear here
    }
  }
}

# If total_count is 0 and you expect results:
# 1. Check attribute configuration in Magento Admin
# 2. Verify field mapping: GET /magento2_product_1/_mapping
# 3. Run: bin/magento indexer:reindex catalogsearch_fulltext
# 4. Check GraphQL schema for filter input registration

10. Zusammenfassung

OpenSearch und Magento GraphQL arbeiten über mehrere Abstraktionsschichten zusammen: Der Resolver übersetzt GraphQL-Argumente in SearchCriteria-Objekte, der Suchadapter übersetzt diese in OpenSearch-Query-DSL-Objekte, und das Ergebnis wird mit Datenbankdaten kombiniert, bevor es als GraphQL-Response zurückgegeben wird. Diese Architektur ist leistungsfähig, erfordert aber Kenntnisse auf allen Ebenen für eine korrekte Konfiguration und Performance-Optimierung.

Die wichtigsten Hebel für performante GraphQL-Suche in Magento: Alle relevanten Filterattribute als filterable konfigurieren, den Index aktuell halten, Aggregationen für Facetten-Filter nutzen und die Nachlad-Schicht aus der Datenbank minimieren, indem möglichst viele Felder im Index vorhanden sind. Das ist kein einmaliger Setup-Schritt — Indexierungsstrategie und OpenSearch-Konfiguration müssen bei jedem neuen Attribut und jedem neuen Custom Module mitgedacht werden.

OpenSearch und Magento GraphQL — Das Wichtigste auf einen Blick

Architektur

Resolver → SearchCriteria → Suchadapter → OpenSearch-Query → IDs → Datenbankabfrage für Details.

Indexierung

Nur indexierte Attribute können als GraphQL-Filter ohne DB-Fallback verwendet werden. Aggregations erfordern OpenSearch-Pfad.

Konfiguration

Attribut als filterable markieren, schema.graphqls erweitern, Index neu aufbauen. Drei Schritte für jeden Custom Filter.

Diagnose

Leere Aggregations = OpenSearch nicht aktiv. Leere Ergebnisse = Index veraltet oder Attribut-Mapping falsch.

11. FAQ: OpenSearch und Magento GraphQL

1Wann verwendet Magento OpenSearch statt DB?
Immer bei search-Argument. Bei filter-only: nur wenn alle Filterattribute im Index als filterable konfiguriert sind. Sonst DB-Fallback.
2Warum gibt aggregations ein leeres Array zurück?
OpenSearch-Pfad wird nicht verwendet — DB-Fallback. Ursache: Filterattribut nicht als "Used in Layered Navigation" aktiviert. Index neu aufbauen.
3Gibt OpenSearch vollständige Produktdaten zurück?
Nein. IDs und Scores. Vollständige Details kommen in einer zweiten Datenbankabfrage — das ist Magento's zweistufige Sucharchitektur.
4Eigenes Attribut für GraphQL-Filter konfigurieren?
1) Attribut als filterable markieren. 2) schema.graphqls erweitern. 3) indexer:reindex catalogsearch_fulltext ausführen.
5text vs. keyword im OpenSearch-Mapping?
text = tokenisiert für Volltext. keyword = exakter Wert für Filter. Viele Felder haben beide als Multi-Field.
6Warum liefert Kategoriefilter leere Ergebnisse?
Index veraltet. Kategorie-IDs im Produkt-Index stimmen nicht mit DB überein. Fix: indexer:reindex catalog_category_product und catalogsearch_fulltext.
7Wie OpenSearch-Query von Magento debuggen?
OpenSearch Slow-Log oder Dashboard. Xdebug im Suchadapter. Die gesendete Query-DSL zeigt Filter, Gewichtungen und Aggregations.
8Auswirkung eines veralteten Index auf GraphQL?
Fehlende oder falsche Produkte, falsche Aggregationszähler. Scheduled Indexing oder mview für regelmäßige Aktualisierung in Produktion.
9Suchfeld-Gewichtungen anpassen?
Ja, über Admin-Konfiguration oder search_request.xml. Steuert, welche Felder bei Volltext-Suchen stärker berücksichtigt werden.
10catalogsearch_fulltext vs. catalog_category_product?
catalogsearch_fulltext = OpenSearch-Produktindex. catalog_category_product = DB-Zuordnungstabelle. Beide müssen für korrekte Kategoriefilter aktuell sein.