Build the mental model
In Elasticsearch, an index is roughly analogous to a PostgreSQL table: it is a container of similarly structured JSON documents — a `tutorials` index might hold every tutorial document. Each document is a JSON object with a unique `_id`, and unlike a PostgreSQL row, a document can naturally hold nested objects and arrays of objects without needing a join table. Mapping is the schema-like definition that declares each field's data type (text, keyword, integer, date, and so on) within an index, serving the same purpose as `CREATE TABLE` column definitions in PostgreSQL. A real difference from PostgreSQL, though, is that if you don't specify a mapping explicitly, Elasticsearch's dynamic mapping auto-detects field types — convenient for quick prototyping, but risky in production because the auto-detected type may not be the one you actually wanted (for example, a `price` field silently detected as a string). Think of mapping like a screenplay's script format: just as a script format tells a reader how to parse each element (dialogue, action, scene heading), mapping tells Elasticsearch how to index and search each field.
Connect it to a real scenario
Design the Tutorial Platform search index as `tutorials`, where each document has `title`, `body`, `tags` (an array), `authorName`, `publishedAt`, and `difficulty` fields. Define an explicit mapping — `title` as `text` for full-text search, `tags` as `keyword` for exact filtering and facets, and `publishedAt` as `date` — rather than trusting dynamic mapping to guess correctly. When a row from PostgreSQL's `tutorials` table becomes an Elasticsearch document, flatten related rows from the `lessons` table into a single nested array inside that document, so no join is needed at search time.
Try the working example
PUT /tutorials
{
"mappings": {
"properties": {
"title": { "type": "text" },
"body": { "type": "text" },
"tags": { "type": "keyword" },
"authorName": { "type": "keyword" },
"publishedAt": { "type": "date" },
"difficulty": { "type": "keyword" }
}
}
}You can create a `tutorials` index with an explicit mapping.5-minute try-it
Write a mapping for a `comments` index with `body` (text), `authorId` (keyword), `createdAt` (date), and `upvotes` (integer) fields.
One important caution
Skipping an explicit mapping and letting dynamic mapping guess field types — a `tags` field auto-detected as `text` instead of `keyword` breaks exact-match filtering.
Copying the PostgreSQL row structure directly instead of denormalizing related table data (like lessons) into a nested array — every search query then needs join-like logic again.