RousselTMLEARNING

Article · OpenSearch: from discovery to expertise

Indexing and searching: mapping, DSL, PPL and SQL

1. Declaring your indexes #

Template and mapping.

An index template #

Declare types before the first write: an existing field type cannot change without reindexing.

curl -sk -u 'admin:Str0ng!Passw0rd-2026' -H 'Content-Type: application/json' -X PUT https://localhost:9200/_index_template/logs_app -d '{
  "index_patterns": ["logs-app-*"],
  "template": {
    "settings": {"number_of_shards": 1, "number_of_replicas": 0},
    "mappings": {"properties": {
      "@timestamp": {"type": "date"},
      "level": {"type": "keyword"},
      "service": {"type": "keyword"},
      "message": {"type": "text"},
      "duree_ms": {"type": "integer"}
    }}
  }
}'
TypeForSearch
keywordExact value: level, serviceFilter, aggregation, sort
textFree text: messageFull text, analyzed
date, integer, ipTyped valuesRanges, aggregations, CIDR

2. Indexing #

The bulk API.

Writing in batches #

cat > lot.ndjson <<'EOF'
{"index":{"_index":"logs-app-000001"}}
{"@timestamp":"2026-11-04T10:00:00Z","level":"ERROR","service":"paiement","message":"timeout vers la banque utilisateur=alice","duree_ms":3100}
{"index":{"_index":"logs-app-000001"}}
{"@timestamp":"2026-11-04T10:00:01Z","level":"INFO","service":"paiement","message":"paiement accepté","duree_ms":120}
{"index":{"_index":"logs-app-000001"}}
{"@timestamp":"2026-11-04T10:00:02Z","level":"INFO","service":"panier","message":"article ajouté","duree_ms":40}
EOF
curl -sk -u 'admin:Str0ng!Passw0rd-2026' -H 'Content-Type: application/x-ndjson' \
  -X POST 'https://localhost:9200/_bulk?refresh=true' --data-binary @lot.ndjson
Best practice: always use _bulk for large volumes, and read "errors" in the response: the HTTP code stays 200 even when documents are refused. Avoid refresh=true in production; here it lets you read the result immediately.

3. Searching #

Query DSL, aggregations, PPL and SQL.

Search #

In a bool, must counts towards the score, while filter only says yes or no, and is cached. Put in filter everything that does not need relevance.

curl -sk -u 'admin:Str0ng!Passw0rd-2026' -H 'Content-Type: application/json' -X POST 'https://localhost:9200/logs-app-*/_search' -d '{
  "query": {"bool": {
    "must":   [{"match": {"message": "banque"}}],
    "filter": [{"term": {"service": "paiement"}}]
  }}
}'

Aggregations #

curl -sk -u 'admin:Str0ng!Passw0rd-2026' -H 'Content-Type: application/json' -X POST 'https://localhost:9200/logs-app-*/_search' -d '{
  "size": 0,
  "aggs": {"par_service": {
    "terms": {"field": "service"},
    "aggs": {"p95": {"percentiles": {"field": "duree_ms", "percents": [95]}}}
  }}
}'

Result of our test: paiement has 2 documents (p95 of 3100 ms) and panier 1 (p95 of 40 ms).

PPL and SQL #

To explore logs, PPL chains operations with |, like a shell.

curl -sk -u 'admin:Str0ng!Passw0rd-2026' -H 'Content-Type: application/json' -X POST https://localhost:9200/_plugins/_ppl \
  -d '{"query":"source=logs-app-* | where service=\"paiement\" | stats count() by level"}'

curl -sk -u 'admin:Str0ng!Passw0rd-2026' -H 'Content-Type: application/json' -X POST https://localhost:9200/_plugins/_sql \
  -d '{"query":"SELECT service, COUNT(*) n FROM logs-app-000001 GROUP BY service"}'

📄 Indexing and searching in OpenSearch: mapping, DSL, PPL and SQL →

My progress

  • ⏱ Estimated time : ≈ 7 min

Sign in to track your progress and take notes. Sign in

💬 Ask a question

Recommended Articles

Query DSL et agrégations avancées Elasticsearch, avec ES|QL

Écrire des requêtes Elasticsearch avancées : bool, filter et score, nested, function_score et per...

OpenSearch Dashboards, alerting and observability

Explore data in OpenSearch Dashboards, create alert monitors and discover Trace Analytics, Event ...

Installing OpenSearch and OpenSearch Dashboards

Install OpenSearch with Docker Compose or the archive: initial password, vm.max_map_count, demo c...

Feeding OpenSearch: ingest pipelines and Data Prepper

Transform data with ingest pipelines, collect with Data Prepper, receive OTLP and avoid the dynam...

Data streams et templates Elasticsearch : component templates, index templates et séries temporelles

Gérer les données horodatées avec les data streams : index templates et component templates, conv...

Exploring data in OpenObserve: SQL, PromQL and VRL

Search with SQL, query metrics with PromQL, optimize a stream (indexes, partitions, retention) an...

Bonnes pratiques Elasticsearch : mappings, shards, cycle de vie et exploitation

Bonnes pratiques Elasticsearch : dimensionnement des shards, mappings explicites, templates, ILM,...

Mappings et analyse de texte Elasticsearch : types de champs, analyseurs et mapping dynamique

Maîtriser les mappings Elasticsearch : types de champs (text, keyword, numériques, date, ip, nest...

OpenSearch: concepts, architecture and differences with Elasticsearch

Understanding OpenSearch: project origin, license, differences with Elasticsearch, indexes, shard...

Support us

♥ SUPPORT US

Support RousselTM Learning

Courses, articles, labs and certificates stay free with no intrusive ads. A voluntary contribution, of any amount you choose, pays for hosting, lab environments and new content.

Contribute with PayPal Any amount · card or PayPal accountLearn more
QR code PayPal
Or scan this QR code with your phone

Thank you, every contribution counts!