28 Suchen in OpenSearch

Die Suche ist das Herzstück von OpenSearch. In diesem Kapitel lernen Sie, wie Sie die leistungsfähigen Suchfunktionen optimal nutzen können. Wir beginnen mit einfachen Suchanfragen und arbeiten uns schrittweise zu komplexeren Szenarien vor, immer mit dem Fokus auf praktische Anwendungsfälle.

28.1 Grundlagen der Suche verstehen

Bevor wir in die technischen Details eintauchen, ist es wichtig zu verstehen, wie OpenSearch Suchanfragen verarbeitet. Wenn Sie eine Suchanfrage stellen, durchläuft sie mehrere Phasen:

  1. Die Anfrage wird analysiert und in einen Suchplan umgewandelt
  2. Relevante Shards werden identifiziert
  3. Die Suche wird parallel auf den Shards ausgeführt
  4. Die Ergebnisse werden zusammengeführt und sortiert

28.1.1 Anatomie einer Suchanfrage

Lassen Sie uns mit einer einfachen Suchanfrage beginnen:

GET /products/_search
{
  "query": {
    "match": {
      "description": "wasserdichte kamera"
    }
  }
}

Diese scheinbar einfache Anfrage zeigt bereits wichtige Konzepte:

Die Antwort enthält wichtige Metainformationen:

{
  "took": 5,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 3,
      "relation": "eq"
    },
    "max_score": 0.9267189,
    "hits": [...]
  }
}

Aus dieser Antwort können wir ablesen:

28.2 Query-Typen im Detail

OpenSearch bietet verschiedene Query-Typen für unterschiedliche Suchanforderungen. Lassen Sie uns die wichtigsten im Detail betrachten.

28.2.1 Term-Level Queries

Term-Level Queries sind ideal für exakte Übereinstimmungen, etwa bei IDs, Kategorien oder Statuswerten:

GET /products/_search
{
  "query": {
    "term": {
      "category.keyword": "Elektronik"
    }
  }
}

Diese Art der Suche ist besonders nützlich für:

28.2.2 Full-Text Queries

Full-Text Queries sind die Wahl für Textsuche mit natürlicher Sprache:

GET /products/_search
{
  "query": {
    "match": {
      "description": {
        "query": "leichte kompakte kamera",
        "operator": "and"
      }
    }
  }
}

Der “operator”: “and” bedeutet, dass alle Suchbegriffe gefunden werden müssen. Ohne diese Angabe würde OpenSearch standardmäßig “or” verwenden.

28.2.3 Phrase Queries

Wenn die Reihenfolge der Suchbegriffe wichtig ist:

GET /products/_search
{
  "query": {
    "match_phrase": {
      "description": {
        "query": "wasserdichte digitalkamera",
        "slop": 1
      }
    }
  }
}

Der “slop”-Parameter gibt an, wie viele Positionen die Wörter voneinander entfernt sein dürfen. Ein Wert von 1 würde auch “wasserdichte kompakte digitalkamera” finden.

28.3 Komplexe Suchanfragen erstellen

In der Praxis kombinieren wir oft verschiedene Query-Typen für präzisere Suchergebnisse.

28.3.1 Boolean Queries

Die Bool Query ist das Hauptwerkzeug für komplexe Suchanfragen:

GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "kamera"
          }
        }
      ],
      "filter": [
        {
          "range": {
            "price": {
              "gte": 100,
              "lte": 500
            }
          }
        },
        {
          "term": {
            "in_stock": true
          }
        }
      ],
      "should": [
        {
          "match": {
            "description": "wasserdicht"
          }
        }
      ],
      "minimum_should_match": 0
    }
  }
}

Diese Anfrage demonstriert mehrere wichtige Konzepte:

28.3.2 Aggregationen für Analysen

Aggregationen ermöglichen statistische Analysen und Facettierung:

GET /products/_search
{
  "size": 0,
  "aggs": {
    "price_ranges": {
      "range": {
        "field": "price",
        "ranges": [
          { "to": 100 },
          { "from": 100, "to": 500 },
          { "from": 500 }
        ]
      },
      "aggs": {
        "avg_rating": {
          "avg": {
            "field": "rating"
          }
        }
      }
    },
    "top_categories": {
      "terms": {
        "field": "category.keyword",
        "size": 5
      }
    }
  }
}

Diese Anfrage:

28.4 Relevanz und Scoring optimieren

Die Relevanz der Suchergebnisse ist entscheidend für die Benutzerfreundlichkeit.

28.4.1 Boosting wichtiger Felder

GET /products/_search
{
  "query": {
    "multi_match": {
      "query": "kamera stativ",
      "fields": [
        "name^3",
        "description"
      ]
    }
  }
}

Der “^3” Operator gibt dem “name”-Feld dreimal mehr Gewicht als dem “description”-Feld.

28.4.2 Function Score Queries

Function Score Queries ermöglichen komplexe Score-Berechnungen:

GET /products/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "description": "kamera"
        }
      },
      "functions": [
        {
          "field_value_factor": {
            "field": "rating",
            "factor": 1.2,
            "missing": 1
          }
        },
        {
          "decay_exponential": {
            "price": {
              "origin": "100",
              "scale": "100",
              "decay": 0.5
            }
          }
        }
      ],
      "boost_mode": "multiply",
      "score_mode": "sum"
    }
  }
}

Diese Anfrage:

28.5 Performance-Optimierung

Die Optimierung von Suchanfragen ist entscheidend für die Performance.

28.5.1 Filtern statt Queries

Wenn keine Relevanzberechnung benötigt wird, verwenden Sie Filter:

# Weniger effizient
GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "price": {
              "gte": 100
            }
          }
        }
      ]
    }
  }
}

# Effizienter
GET /products/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "price": {
              "gte": 100
            }
          }
        }
      ]
    }
  }
}

Filter werden gecacht und sind effizienter, da sie keine Scores berechnen.

28.5.2 Source Filtering

Reduzieren Sie die zurückgegebenen Felder:

GET /products/_search
{
  "_source": ["name", "price", "category"],
  "query": {
    "match_all": {}
  }
}

28.6 Praktische Anwendungsfälle

28.6.1 E-Commerce Produktsuche

Eine typische Produktsuche mit Facettierung:

GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "multi_match": {
            "query": "smartphone",
            "fields": ["name^2", "description"]
          }
        }
      ],
      "filter": [
        {
          "term": { "in_stock": true }
        }
      ]
    }
  },
  "aggs": {
    "price_ranges": {
      "range": {
        "field": "price",
        "ranges": [
          { "to": 300 },
          { "from": 300, "to": 600 },
          { "from": 600 }
        ]
      }
    },
    "brands": {
      "terms": {
        "field": "brand.keyword"
      }
    }
  },
  "sort": [
    { "_score": "desc" },
    { "price": "asc" }
  ]
}

28.6.2 Dokumentensuche mit Highlighting

GET /documents/_search
{
  "query": {
    "match_phrase": {
      "content": "OpenSearch Entwicklung"
    }
  },
  "highlight": {
    "fields": {
      "content": {
        "fragment_size": 150,
        "number_of_fragments": 3,
        "pre_tags": ["<strong>"],
        "post_tags": ["</strong>"]
      }
    }
  }
}