Skip to content
ExponaBLOG
ELASTICSEARCH & SEARCH ENGINEERING · DAY 058 / 100

semantic_text field in Elasticsearch & Search Engineering

Simpler semantic search setup.

Expona Admin6 min read

Introduction

Before Elasticsearch 8.11, building semantic search meant orchestrating embeddings yourself—spinning up inference endpoints, managing chunking logic, and wiring it all into your indexing pipeline. The semantic_text field in Elasticsearch & Search Engineering flips that script by automating embeddings generation, eliminating boilerplate, and letting teams ship semantic capabilities in days instead of weeks. If you've felt friction setting up vector search, this field type is designed to remove it.

What is semantic_text and why it matters

The semantic_text field type is a managed field that automatically generates embeddings for your documents at index time using an inference endpoint you configure. Unlike the raw dense_vector field, which requires you to compute embeddings before sending data to Elasticsearch, semantic_text accepts plain text, invokes your inference service transparently, and stores both the original text and embeddings internally.

In production environments—especially e-commerce platforms, SaaS knowledge bases, and ride-hailing support systems—this means fewer ETL layers, less operational overhead, and a cleaner mental model. Your indexing code looks like any other field mapping; the complexity shifts to configuration rather than application logic.

Automatic embedding generation

When you index a document with a semantic_text field, Elasticsearch intercepts the value, sends it to your inference endpoint, receives the embedding vector, and indexes both the text and vector in the same field. You don't write the embedding yourself—it's derived from the text automatically.

Here's a mapping example for a product catalog:

json
{
  "mappings": {
    "properties": {
      "product_id": {
        "type": "keyword"
      },
      "description": {
        "type": "semantic_text",
        "inference_id": "my-inference-endpoint"
      },
      "category": {
        "type": "keyword"
      }
    }
  }
}

When you index a product:

json
POST /products/_doc
{
  "product_id": "SKU-12345",
  "description": "Wireless noise-cancelling headphones with 30-hour battery life",
  "category": "electronics"
}

Elasticsearch sends "Wireless noise-cancelling headphones with 30-hour battery life" to your inference endpoint, gets back a 384-dimensional vector (or whatever your model outputs), and stores both. No embedding computation in your application code; no separate vectorization pipeline.

This is especially valuable in high-throughput scenarios. Teams at ride-hailing companies handling thousands of driver feedback documents per day appreciate that embeddings generation is non-blocking and pooled within Elasticsearch, not competing for resources in their application servers.

Using an inference endpoint

The inference endpoint is where the actual embedding model runs. It can be:

  • Elasticsearch Service-managed: Models like E5, multilingual-E5, or Cohere's embed-english-v3.0, provisioned and scaled by Elastic.
  • Self-hosted: Your own ONNX runtime or Hugging Face Inference Server, callable via HTTP.
  • Third-party SaaS: OpenAI, Cohere, or Mistral APIs.

Creating an inference endpoint for Elasticsearch Service (using Elastic's managed models) looks like this:

json
PUT _inference/text_embedding/my-inference-endpoint
{
  "model_id": "multilingual-e5-small",
  "service": "elastic",
  "service_settings": {
    "model_id": "multilingual-e5-small"
  },
  "task_settings": {}
}

If you're running your own inference container, you'd configure it differently:

json
PUT _inference/text_embedding/custom-embedding-endpoint
{
  "service": "huggingface",
  "service_settings": {
    "url": "http://inference-container:8000/embed",
    "model_id": "sentence-transformers/all-MiniLM-L6-v2"
  }
}

The endpoint is referenced in your field mapping via the inference_id parameter. Elasticsearch handles retries, batching of requests, and caching to avoid redundant embedding calls. In a travel platform with millions of property descriptions, this pooling saves significant compute and latency.

Automatic chunking and text handling

One challenge with embedding large text blocks is that most embedding models have token limits (often 512 or 1024 tokens). A product description, article, or support ticket might exceed that. The semantic_text field can handle this with chunking.

When you configure chunking:

json
PUT /articles
{
  "mappings": {
    "properties": {
      "title": {
        "type": "keyword"
      },
      "body": {
        "type": "semantic_text",
        "inference_id": "my-inference-endpoint",
        "model_settings": {
          "chunking_settings": {
            "strategy": "sentence",
            "max_chunk_size": 400,
            "overlap": 50
          }
        }
      }
    }
  }
}

Elasticsearch automatically splits the text into overlapping chunks (400 characters here, with 50-character overlap), embeds each chunk, and stores them. At query time, your semantic query matches against all chunks, letting you retrieve highly relevant passages even from long documents.

In a CRM scenario, this is powerful: a customer support team can upload a long ticket thread, and semantic search will surface the most relevant paragraphs, not force you to pick a single representative text for the entire record.

Chunking strategies include:

  • sentence: Split on sentence boundaries (best for narrative text).
  • word: Split on word boundaries (good for mixed content).
  • passage: Fixed-size overlapping windows (more predictable).

Querying with semantic queries

Once you've indexed documents with semantic_text fields, querying is intuitive. Use the semantic query type, pass your natural language query string, and Elasticsearch embeds it on-the-fly using the same inference endpoint:

json
POST /products/_search
{
  "query": {
    "semantic": {
      "description": {
        "query": "quiet headphones with long battery",
        "boost": 1.5
      }
    }
  },
  "size": 10
}

Elasticsearch embeds "quiet headphones with long battery" using the same inference endpoint, computes similarity with all stored description embeddings, and ranks results by semantic relevance.

You can combine semantic queries with exact-match filters for hybrid retrieval:

json
POST /products/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "semantic": {
            "description": {
              "query": "wireless charging"
            }
          }
        }
      ],
      "filter": [
        {
          "term": {
            "category": "electronics"
          }
        },
        {
          "range": {
            "price": {
              "lte": 200
            }
          }
        }
      ]
    }
  }
}

This pattern is standard in e-commerce: semantic search finds conceptually relevant products, then facets and price filters narrow the results. It's also common in SaaS: embed all knowledge base articles, then filter by product version or team before ranking semantically.

Common mistakes

Assuming embeddings are instant: Inference requests add latency. Index throughput will be slower than keyword indexing. Plan for this in your bulk indexing jobs; consider indexing in batches or during off-peak hours.

Not testing the inference endpoint before scaling: Network timeouts, model errors, or misconfigured URLs are easy to miss in development. Always test end-to-end indexing in staging before production rollout.

Ignoring chunking overhead: If you enable chunking on large text fields without testing, you may end up with thousands of chunks per document. Monitor chunk counts during initial indexing to validate your settings.

Mixing field types inconsistently: If some product descriptions use semantic_text and others use plain text`, queries become inconsistent. Commit to the field type early in your schema design.

Overloading inference endpoints: If your cluster is indexing 10,000 documents per second and each document has a semantic_text field, your inference endpoint must handle the volume. Monitor inference latency and scale horizontally or use batching if needed.

Key takeaways

  • semantic_text automates embedding generation, removing the need for separate vectorization pipelines in your application.
  • Inference endpoints—managed by Elastic, self-hosted, or third-party—define the embedding model; they're referenced by field mappings.
  • Chunking strategies handle long text fields, storing overlapping chunks and retrieving relevant passages at query time.
  • Semantic queries embed your search string on-the-fly and rank results by vector similarity, often combined with exact-match filters for hybrid retrieval.
  • Plan for indexing latency, test inference endpoints thoroughly, and monitor chunk counts and endpoint load in production.
  • This field type reduces complexity and accelerates semantic search adoption in teams shipping e-commerce, SaaS, and knowledge-base features.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles