Das Mapping in OpenSearch ist vergleichbar mit dem Datenbankschema in relationalen Datenbanken - es definiert die Struktur Ihrer Daten. Allerdings geht Mapping in OpenSearch weit darüber hinaus: Es bestimmt nicht nur die Datentypen, sondern auch, wie OpenSearch Ihre Daten verarbeitet, analysiert und durchsucht. Lassen Sie uns gemeinsam erkunden, wie Sie Mapping effektiv einsetzen können.
Wenn Sie aus der Welt der relationalen Datenbanken kommen, ist der Übergang zum Mapping in OpenSearch zunächst eine Umstellung. In einer relationalen Datenbank würden Sie vielleicht eine Produkttabelle so definieren:
CREATE TABLE products (
id VARCHAR(50) PRIMARY KEY,
name VARCHAR(100) NOT NULL,
description TEXT,
price DECIMAL(10,2),
category VARCHAR(50),
created_at TIMESTAMP
);In OpenSearch definieren wir eine ähnliche Struktur als Mapping:
PUT /products
{
"mappings": {
"properties": {
"id": {
"type": "keyword"
},
"name": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
},
"description": {
"type": "text"
},
"price": {
"type": "float"
},
"category": {
"type": "keyword"
},
"created_at": {
"type": "date"
}
}
}
}
Der wichtigste Unterschied: Das OpenSearch Mapping bietet mehr Flexibilität und Kontrolle über die Suche. Beachten Sie zum Beispiel, wie das ‘name’-Feld sowohl als ‘text’ (für Volltextsuche) als auch als ‘keyword’ (für exakte Suchen) indiziert wird.
Lassen Sie uns die wichtigsten Datentypen und ihre Anwendungsfälle genauer betrachten.
Der Unterschied zwischen ‘text’ und ‘keyword’ ist einer der wichtigsten Aspekte des Mappings:
PUT /articles
{
"mappings": {
"properties": {
"title": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
},
"tags": {
"type": "keyword"
}
}
}
}
Wenn wir ein Dokument mit diesem Mapping indizieren:
POST /articles/_doc
{
"title": "Einführung in OpenSearch Mapping",
"tags": ["tutorial", "opensearch", "mapping"]
}
Dann wird:
OpenSearch bietet verschiedene numerische Datentypen. Die Wahl des richtigen Typs beeinflusst sowohl die Speichereffizienz als auch die Genauigkeit:
PUT /sensor_data
{
"mappings": {
"properties": {
"temperature": {
"type": "float",
"coerce": true
},
"pressure": {
"type": "double"
},
"readings_count": {
"type": "integer"
},
"precise_measurement": {
"type": "scaled_float",
"scaling_factor": 100
}
}
}
}
Die Wahl des Typs sollte sich an Ihren Anforderungen orientieren:
Die korrekte Handhabung von Datumsfeldern ist entscheidend für zeitbasierte Analysen:
PUT /events
{
"mappings": {
"properties": {
"created_at": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis",
"ignore_malformed": false
},
"local_time": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss",
"ignore_malformed": true
}
}
}
}
Beachten Sie die verschiedenen Format-Optionen und wie ‘ignore_malformed’ hilft, mit fehlerhaften Daten umzugehen.
OpenSearch bietet zwei grundlegende Ansätze zum Mapping: dynamisch und explizit.
Beim dynamischen Mapping erkennt OpenSearch automatisch die Datentypen:
# Dokument ohne explizites Mapping indizieren
POST /logs/_doc
{
"timestamp": "2024-01-13T12:00:00Z",
"message": "Server started",
"response_time": 123,
"tags": ["startup", "success"]
}
OpenSearch erstellt automatisch folgendes Mapping:
{
"logs": {
"mappings": {
"properties": {
"timestamp": {
"type": "date"
},
"message": {
"type": "text"
},
"response_time": {
"type": "long"
},
"tags": {
"type": "text"
}
}
}
}
}
Dieses Verhalten können wir steuern:
PUT /logs
{
"mappings": {
"dynamic": "strict",
"dynamic_templates": [
{
"strings_as_keywords": {
"match_mapping_type": "string",
"mapping": {
"type": "keyword"
}
}
}
]
}
}
In Produktivumgebungen sollten Sie explizites Mapping verwenden:
PUT /customer_data
{
"mappings": {
"dynamic": "strict",
"properties": {
"id": {
"type": "keyword"
},
"name": {
"properties": {
"first": {
"type": "text",
"fields": {
"raw": {
"type": "keyword",
"ignore_above": 256
}
}
},
"last": {
"type": "text",
"fields": {
"raw": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
},
"email": {
"type": "keyword",
"normalizer": "lowercase"
},
"age": {
"type": "integer"
},
"account_balance": {
"type": "scaled_float",
"scaling_factor": 100
},
"address": {
"type": "object",
"properties": {
"street": {
"type": "text"
},
"city": {
"type": "keyword"
},
"country": {
"type": "keyword"
},
"location": {
"type": "geo_point"
}
}
}
}
}
}
Dieses Beispiel zeigt wichtige Mapping-Konzepte:
PUT /technical_documents
{
"mappings": {
"properties": {
"title": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
},
"index_prefixes": {
"min_chars": 2,
"max_chars": 5
}
},
"content": {
"type": "text",
"term_vector": "with_positions_offsets",
"store": true
}
}
}
}
Diese Konfiguration ermöglicht:
PUT /user_activity
{
"mappings": {
"properties": {
"user_id": {
"type": "keyword",
"index": true,
"doc_values": true
},
"session_data": {
"type": "object",
"enabled": false
},
"last_login": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis",
"ignore_malformed": true,
"null_value": null
}
}
}
}
Die Parameter steuern:
PUT /logs_optimized
{
"mappings": {
"properties": {
"message": {
"type": "text",
"norms": false
},
"status_code": {
"type": "short"
},
"response_time": {
"type": "integer",
"doc_values": false
}
}
}
}
Diese Optimierungen:
PUT /product_catalog
{
"mappings": {
"properties": {
"sku": {
"type": "keyword",
"eager_global_ordinals": true
},
"name": {
"type": "text",
"index_options": "positions"
},
"description": {
"type": "text",
"index_options": "freqs"
}
}
}
}
Diese Einstellungen optimieren: