19 Mapping APIs

19.1 Was ist Mapping und warum ist es wichtig?

Stellen Sie sich Mapping als den Bauplan eines Hauses vor. Wie ein Architekt genau festlegt, wo Räume, Türen und Fenster sein sollen, definiert das Mapping die Struktur Ihrer Daten in OpenSearch. Es legt fest, wie Informationen gespeichert, indiziert und durchsucht werden können.

19.1.1 Die Bedeutung des Mappings

Ein durchdachtes Mapping ist entscheidend für:

19.2 Die Grundlagen des Mappings

19.2.1 Explizites vs. Dynamisches Mapping

OpenSearch bietet zwei Wege, ein Mapping zu erstellen:

// Explizites Mapping
PUT /customer-index
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      },
      "age": {
        "type": "integer"
      }
    }
  }
}

// Dynamisches Mapping lässt OpenSearch die Typen erkennen
POST /dynamic-index/_doc
{
  "name": "John Doe",     // Wird als "text" erkannt
  "age": 30,             // Wird als "integer" erkannt
  "joined": "2025-01-14" // Wird als "date" erkannt
}

19.2.2 Die wichtigsten Datentypen

OpenSearch bietet eine Vielzahl von Datentypen für unterschiedliche Anwendungsfälle:

  1. Text-Datentypen:
{
  "properties": {
    "title": {
      "type": "text",        // Volltext-Suche
      "fields": {
        "raw": {
          "type": "keyword"  // Exakte Suche & Aggregationen
        }
      }
    }
  }
}
  1. Numerische Datentypen:
{
  "properties": {
    "price": {
      "type": "float",
      "coerce": true        // Automatische Typkonvertierung
    },
    "quantity": {
      "type": "integer"
    }
  }
}
  1. Datum und Zeit:
{
  "properties": {
    "created_at": {
      "type": "date",
      "format": "strict_date_optional_time||epoch_millis"
    }
  }
}

19.3 Fortgeschrittene Mapping-Konzepte

19.3.1 Multi-Fields: Ein Feld, mehrere Verwendungszwecke

{
  "properties": {
    "email": {
      "type": "text",
      "fields": {
        "raw": {
          "type": "keyword"
        },
        "analyzed": {
          "type": "text",
          "analyzer": "email_analyzer"
        }
      }
    }
  }
}

19.3.2 Field-Parameter für optimierte Suche

{
  "properties": {
    "description": {
      "type": "text",
      "analyzer": "german",
      "search_analyzer": "german_search",
      "index_options": "positions",
      "store": true,
      "copy_to": "all_fields"
    }
  }
}

19.4 Mapping-Strategien für reale Anwendungsfälle

19.4.1 E-Commerce-Plattform

PUT /products
{
  "mappings": {
    "properties": {
      "sku": {
        "type": "keyword"
      },
      "name": {
        "type": "text",
        "fields": {
          "raw": { "type": "keyword" }
        }
      },
      "description": {
        "type": "text",
        "analyzer": "custom_product_analyzer"
      },
      "price": {
        "type": "scaled_float",
        "scaling_factor": 100
      },
      "inventory": {
        "type": "nested",
        "properties": {
          "warehouse": { "type": "keyword" },
          "quantity": { "type": "integer" },
          "location": { "type": "geo_point" }
        }
      }
    }
  }
}

19.4.2 Logging-System

PUT /logs
{
  "mappings": {
    "properties": {
      "timestamp": {
        "type": "date"
      },
      "level": {
        "type": "keyword"
      },
      "message": {
        "type": "text",
        "index_options": "positions"
      },
      "stack_trace": {
        "type": "text",
        "index": false
      },
      "metrics": {
        "type": "object",
        "enabled": false
      }
    }
  }
}

19.5 Best Practices und Optimierungen

19.5.1 Speicheroptimierung

{
  "properties": {
    "user_id": {
      "type": "long",
      "doc_values": false  // Deaktivieren für nicht-aggregierte Felder
    },
    "email": {
      "type": "keyword",
      "ignore_above": 256  // Limitiert Feldlänge
    }
  }
}

19.5.2 Such-Optimierung

{
  "properties": {
    "title": {
      "type": "text",
      "index_prefixes": {  // Optimiert Prefix-Suchen
        "min_chars": 1,
        "max_chars": 10
      }
    }
  }
}

19.6 Mapping-Updates und Reindexierung

19.6.1 Neue Felder hinzufügen

PUT /my-index/_mapping
{
  "properties": {
    "new_field": {
      "type": "keyword"
    }
  }
}

19.6.2 Reindexierung für Änderungen am Mapping

POST /_reindex
{
  "source": {
    "index": "old-index"
  },
  "dest": {
    "index": "new-index"
  },
  "script": {
    "source": "ctx._source.new_field = ctx._source.remove('old_field')"
  }
}

19.7 Mapping-Analyse und Debugging

19.7.1 Mapping-Analyse

GET /my-index/_mapping

GET /my-index/_mapping/field/specific.field

19.7.2 Feldtyp-Überprüfung

POST /my-index/_analyze
{
  "field": "my_field",
  "text": "Sample text"
}

19.8 Performance-Implikationen verschiedener Mapping-Entscheidungen

19.8.1 Text vs. Keyword

Text-Felder sind ideal für Volltextsuche, verbrauchen aber mehr Speicher:

{
  "properties": {
    "email": {
      "type": "text",  // Ermöglicht Volltextsuche
      "fields": {
        "raw": {
          "type": "keyword"  // Ermöglicht effiziente Aggregationen
        }
      }
    }
  }
}

19.8.2 Nested vs. Object

Nested-Typen bieten mehr Genauigkeit, sind aber ressourcenintensiver:

{
  "properties": {
    "comments": {
      "type": "nested",  // Präzise Suche in Arrays von Objekten
      "properties": {
        "author": { "type": "keyword" },
        "text": { "type": "text" }
      }
    }
  }
}

19.9 Migration und Versionierung

19.9.1 Alias-basierte Migration

// Neuen Index mit aktualisiertem Mapping erstellen
PUT /users-v2
{
  "mappings": {
    "properties": {
      "name": { "type": "text" },
      "email": { "type": "keyword" }
    }
  }
}

// Daten reindexieren
POST /_reindex
{
  "source": { "index": "users-v1" },
  "dest": { "index": "users-v2" }
}

// Alias aktualisieren
POST /_aliases
{
  "actions": [
    { "remove": { "index": "users-v1", "alias": "users" }},
    { "add": { "index": "users-v2", "alias": "users" }}
  ]
}

19.10 Zusammenfassung und Best Practices

Ein erfolgreiches Mapping sollte:

  1. Die Datentypen präzise an den Verwendungszweck anpassen
  2. Performance-Implikationen berücksichtigen
  3. Zukünftige Änderungen durch flexible Strukturen ermöglichen
  4. Speichereffizienz und Suchperformance balancieren
  5. Migrations- und Versionierungsstrategien einplanen

Die sorgfältige Planung des Mappings zu Beginn eines Projekts zahlt sich durch bessere Performance, geringere Wartungskosten und höhere Flexibilität aus