Home/Technologies/Elasticsearch

Elasticsearch

Searching product names with a database substring query works while the catalog is small. Customers then expect misspellings to work, relevant matches to appear first, and filters for brand and price. Matching a piece of text is now only part of the job.

Elasticsearch builds a search index over documents. An analyzer turns text into searchable terms, and an inverted index records which documents contain each term. The engine can find candidates and rank them without scanning every product description for each request.

Shay Banon built Elasticsearch on Apache Lucene, exposing search and indexing through a distributed service. An Elasticsearch index is divided into shards; each shard is a Lucene index, and replicas can provide additional copies and read capacity. The number and size of shards become operational choices as the catalog grows.

The requests below use Kibana's Dev Tools Console syntax against a connected Elasticsearch cluster. Create a fresh example index with an explicit mapping:

HTTP
PUT profile-products
{
  "mappings": {
    "properties": {
      "title": { "type": "text" },
      "brand": { "type": "keyword" },
      "category": { "type": "keyword" },
      "price": { "type": "double" }
    }
  }
}

The title is analyzed for full-text search. Brand and category remain exact keyword values suitable for filters and aggregations. That distinction matters: splitting a brand into search terms would be awkward when the interface needs one exact brand filter.

Add two documents, using stable product IDs in their URLs:

HTTP
PUT profile-products/_doc/42?refresh=wait_for
{
  "title": "Wireless mechanical keyboard",
  "brand": "Acme",
  "category": "keyboards",
  "price": 79
}

PUT profile-products/_doc/43?refresh=wait_for
{
  "title": "Compact wireless keyboard",
  "brand": "Keen",
  "category": "keyboards",
  "price": 89
}

refresh=wait_for waits until these writes become visible to search, making the next request predictable. Ordinary indexing is near real time: an acknowledged write is not necessarily searchable immediately. Waiting on every production write adds latency, so choose that behavior around the application's needs.

Now search with a misspelled word, require the keyboard category, and cap the price:

HTTP
GET profile-products/_search
{
  "query": {
    "bool": {
      "must": {
        "match": {
          "title": {
            "query": "wireless keybord",
            "operator": "and",
            "fuzziness": "AUTO"
          }
        }
      },
      "filter": [
        { "term": { "category": "keyboards" } },
        { "range": { "price": { "lte": 100 } } }
      ]
    }
  },
  "aggs": {
    "brands": { "terms": { "field": "brand" } }
  }
}

The match query analyzes the input and allows fuzzy matches for the typo. operator: and requires both search terms. The filters restrict eligibility without adding relevance scores, and the aggregation counts brands among the matching documents. Those counts can populate the catalog's filter controls.

The index still needs to reflect product changes. A feed from the owning database can update documents using the same IDs, while version-aware handling prevents an older event from overwriting a newer product. Keep a way to rebuild the index when mappings or analysis rules change. In this design, checkout validates current stock and price against the owning service rather than a potentially delayed search copy.

The same search machinery supports document retrieval and log exploration. What changes is the document model, the analysis rules, and the balance between indexing volume, retention, and query latency.

Search indexes and derived data follows the update and rebuild path behind this catalog.

Back to technologies