본문으로 건너뛰기 Elasticsearch Complete Guide | Search, Indexing, Aggregations & Performance

Elasticsearch Complete Guide | Search, Indexing, Aggregations & Performance

Elasticsearch Complete Guide | Search, Indexing, Aggregations & Performance

이 글의 핵심

A practical guide to building a strong search stack with Elasticsearch: indexing, queries, aggregations, analyzers, and performance optimization—with real-world examples.

Core takeaways

This is a hands-on guide to building a powerful search engine with Elasticsearch. It covers indexing, queries, aggregations, analyzers, and performance tuning using practical examples.

Real-world experience: While building e-commerce product search on Elasticsearch, we improved search latency by roughly 10× and increased conversion by about 30% by switching to typo-tolerant search.

Introduction: “Database search is slow”

Real-world scenarios

Scenario 1: LIKE queries take ~10 seconds

PostgreSQL LIKE search can be slow. Elasticsearch often answers in ~0.1 seconds.

Scenario 2: You want typo tolerance

Exact-term-only search misses real users. Elasticsearch supports fuzzy search.

Scenario 3: You need complex aggregations

You must compute counts by category, price ranges, and more. Elasticsearch aggregations cover these patterns.


1. What is Elasticsearch?

Key characteristics

Elasticsearch is a distributed search and analytics engine.

Common use cases:

  • Full-text search: products, documents, logs
  • Autocomplete: live query suggestions
  • Analytics: log analysis, metric rollups
  • Recommendations: “more like this” document retrieval

Typical performance targets:

  • Search latency: under 100 ms
  • Indexing throughput: 10,000+ documents/sec (environment-dependent)

2. Installation

Docker

# Example run
docker run -d \
  --name elasticsearch \
  -p 9200:9200 \
  -p 9300:9300 \
  -e "discovery.type=single-node" \
  -e "xpack.security.enabled=false" \
  docker.elastic.co/elasticsearch/elasticsearch:8.12.0

Verify

curl http://localhost:9200

3. Indexing

Create an index

# Create index
# Example run
curl -X PUT "localhost:9200/products" -H 'Content-Type: application/json' -d'
{
  "mappings": {
    "properties": {
      "name": { "type": "text" },
      "description": { "type": "text" },
      "price": { "type": "float" },
      "category": { "type": "keyword" },
      "tags": { "type": "keyword" },
      "created_at": { "type": "date" }
    }
  }
}
'

Add documents

# Single document
curl -X POST "localhost:9200/products/_doc" -H 'Content-Type: application/json' -d'
{
  "name": "Laptop",
  "description": "High performance laptop",
  "price": 1200.00,
  "category": "Electronics",
  "tags": ["laptop", "computer"],
  "created_at": "2026-04-30"
}
'
# Bulk indexing
curl -X POST "localhost:9200/_bulk" -H 'Content-Type: application/json' -d'
{"index":{"_index":"products"}}
{"name":"Mouse","price":25.00,"category":"Electronics"}
{"index":{"_index":"products"}}
{"name":"Keyboard","price":75.00,"category":"Electronics"}
'

4. Search queries

Match query

curl -X GET "localhost:9200/products/_search" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "name": "laptop"
    }
  }
}
'

Multi match

curl -X GET "localhost:9200/products/_search" -H 'Content-Type: application/json' -d'
{
  "query": {
    "multi_match": {
      "query": "laptop",
      "fields": ["name^2", "description"]
    }
  }
}
'

Bool query (compound conditions)

curl -X GET "localhost:9200/products/_search" -H 'Content-Type: application/json' -d'
{
  "query": {
    "bool": {
      "must": [
        { "match": { "category": "Electronics" } }
      ],
      "filter": [
        { "range": { "price": { "gte": 100, "lte": 1000 } } }
      ],
      "should": [
        { "match": { "tags": "laptop" } }
      ]
    }
  }
}
'

Fuzzy search (typo tolerance)

curl -X GET "localhost:9200/products/_search" -H 'Content-Type: application/json' -d'
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "lapto",
        "fuzziness": "AUTO"
      }
    }
  }
}
'

5. Aggregations

Terms aggregation (grouping)

curl -X GET "localhost:9200/products/_search" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "categories": {
      "terms": {
        "field": "category"
      }
    }
  }
}
'

Stats aggregation

curl -X GET "localhost:9200/products/_search" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "price_stats": {
      "stats": {
        "field": "price"
      }
    }
  }
}
'

Histogram

curl -X GET "localhost:9200/products/_search" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "price_ranges": {
      "histogram": {
        "field": "price",
        "interval": 100
      }
    }
  }
}
'

6. Node.js client

Install

npm install @elastic/elasticsearch

Usage

import { Client } from '@elastic/elasticsearch';
const client = new Client({
  node: 'http://localhost:9200',
});
// Search
async function searchProducts(query: string) {
  const result = await client.search({
    index: 'products',
    body: {
      query: {
        multi_match: {
          query,
          fields: ['name^2', 'description'],
        },
      },
    },
  });
  return result.hits.hits.map((hit) => hit._source);
}
// Indexing
async function indexProduct(product: any) {
  await client.index({
    index: 'products',
    body: product,
  });
}
// Autocomplete
async function autocomplete(prefix: string) {
  const result = await client.search({
    index: 'products',
    body: {
      query: {
        match_phrase_prefix: {
          name: prefix,
        },
      },
      size: 5,
    },
  });
  return result.hits.hits.map((hit) => hit._source.name);
}

7. Analyzers

Korean analyzer

# Install nori plugin
bin/elasticsearch-plugin install analysis-nori
curl -X PUT "localhost:9200/products_kr" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        "korean": {
          "type": "custom",
          "tokenizer": "nori_tokenizer",
          "filter": ["lowercase"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "korean"
      }
    }
  }
}
'

8. Performance optimization

Bulk API

// Bulk indexing
async function bulkIndex(products: any[]) {
  const body = products.flatMap((doc) => [
    { index: { _index: 'products' } },
    doc,
  ]);
  await client.bulk({ body });
}

Caching

curl -X PUT "localhost:9200/products/_settings" -H 'Content-Type: application/json' -d'
{
  "index": {
    "requests.cache.enable": true
  }
}
'

Refresh interval

# If you do not need near-real-time search, increase the interval
curl -X PUT "localhost:9200/products/_settings" -H 'Content-Type: application/json' -d'
{
  "index": {
    "refresh_interval": "30s"
  }
}
'

Connecting this to interviews

Indexes, analyzers, queries, and aggregations map cleanly to search, logging, and system design interviews. See the technical interview preparation guide and developer resume & interview guide for how to quantify scale and metrics on your resume.


Summary and checklist

Key points

  • Elasticsearch: distributed search and analytics engine
  • Full-text search: fast, ranked retrieval
  • Fuzzy search: typo tolerance
  • Aggregations: powerful analytics
  • Analyzers: multilingual text processing
  • Scalability: horizontal scaling patterns

Production checklist

  • Elasticsearch cluster topology
  • Index mapping design
  • Analyzer configuration
  • Search query tuning
  • Aggregation implementation
  • Monitoring and alerting
  • Automated backups

  • MongoDB advanced guide
  • Redis advanced guide
  • PostgreSQL advanced guide

Keywords covered in this post

Elasticsearch, Search, Full-Text Search, Indexing, Analytics, ELK Stack