October 1st, 2026
heart1 reaction

Migrating Elasticsearch Mappings to Azure Cosmos DB

Product Manager

This post focuses on one of the most important design tasks when migrating from Elasticsearch to Azure Cosmos DB: translating an Elasticsearch mapping into Azure Cosmos DB container configuration. 

In Elasticsearch, a mapping defines how document fields are stored and indexed. Azure Cosmos DB is schema-agnostic, so there is no single mapping document to translate. Instead, distribute the mapping’s intent across the indexing policy, full-text policy, vector policy, and computed properties. 

The goal is not a line-by-line conversion. It is to preserve the query, filtering, ranking, and retrieval behavior that the application depends on while adopting Azure Cosmos DB’s container-level model. 

Mapping translation at a glance

Elasticsearch  Azure Cosmos DB equivalent 
Mapped fields, index, and field types used for exact-match queries, filters, sorting, and aggregations Indexing policy: included and excluded paths, range indexes, composite indexes, and spatial indexes 
Text fields and analyzers Full-text policy plus a full-text index in the indexing policy 
dense_vector fields and vector index options Container vector policy plus a vector index in the indexing policy 
Runtime fields or values materialized for search Computed properties 

Start by inventorying how each Elasticsearch field is used, not only how it is typed. A field used for filters and sorting translates differently from one used for relevance ranking, even when both contain strings. One Elasticsearch field can also map to more than one Azure Cosmos DB capability. 

Translate by capability

1. Exact-match, filter, sort, and range behavior

Elasticsearch  Azure Cosmos DB 
"properties": {
  "category": { "type": "keyword" },
  "price": { "type": "double" },
  "description": { "type": "text" }
} 
"indexingPolicy": {
  "includedPaths": [
    { "path": "/category/?" },
    { "path": "/price/?" }
  ],
  "excludedPaths": [
    { "path": "/description/?" }
  ]
}

 

What changes: Keep the JSON values and index the paths used by queries. Add a composite index only when a recurring query filters by category and sorts by price; configure the partition key separately. 

2. Full-text fields and analyzers

Elasticsearch  Azure Cosmos DB 
"properties": {
  "description": {
    "type": "text",
    "analyzer": "english"
  },
  "sku": { "type": "keyword" }
} 
"fullTextPolicy": {
  "defaultLanguage": "en-US",
  "fullTextPaths": [
    { "path": "/description",
      "language": "en-US" }
  ]
}

"fullTextIndexes": [
  { "path": "/description" }
] 

What changes: Translate the analyzer’s intent—language-aware tokenization, stemming, and stop-word handling—rather than copying a custom analysis chain. Keep sku in the regular indexing policy for exact matches. 

3. Vector fields

Elasticsearch  Azure Cosmos DB 
"content_vector": {
  "type": "dense_vector",
  "dims": 384,
  "similarity": "cosine",
  "index": true
} 
"vectorEmbeddingPolicy": {
  "vectorEmbeddings": [{
    "path": "/contentVector",
    "dataType": "float32",
    "distanceFunction": "cosine",
    "dimensions": 384
  }]
}

"vectorIndexes": [{
  "path": "/contentVector",
  "type": "quantizedFlat"
}] 

What changes: Preserve the embedding model’s dimensions and similarity function. Select the Azure Cosmos DB vector index type according to data size, filters, latency, and recall. 

4. Derived and runtime values 

Elasticsearch  Azure Cosmos DB 
"runtime": {
  "discountedPrice": {
    "type": "double",
    "script": {
      "source": "emit(doc['price'].value * 0.9)"
    }
  }
} 
"computedProperties": [{
  "name": "discountedPrice",
  "query": "SELECT VALUE c.price * 0.9 FROM c"
}] 

What changes: Rewrite a stable, deterministic derivation as a computed property. Calculate unsupported or external-state logic during ingestion or in the application. 

Recommended migration sequence 

  1. Inventory the mapping and workload. Export mappings, templates, analyzers, vector settings, runtime fields, and the queries that use them. 
  1. Classify every field by behavior. Mark paths for exact filtering or sorting, full-text search, vector search, geospatial queries, or derived values. 
  1. Design the container policies together. Resolve overlaps—for example, a description can be available to normal queries, full-text search, and vector retrieval. 
  1. Validate with representative data and queries. Compare result correctness, relevance ordering, latency, RU consumption, and write cost. 
  1. Roll out deliberately. Apply policy changes before dependent queries, monitor index transformation where applicable, and keep a rollback path. 

Key takeaway 

An Elasticsearch mapping is best treated as a statement of search intent, not a schema to reproduce. In Azure Cosmos DB, that intent is expressed through coordinated container policies: the indexing policy handles standard query access paths, the full-text policy handles analyzed text, the vector policy handles embeddings, and computed properties handle reusable derived values. Translating by workload preserves behavior while avoiding unnecessary indexes and migration-era assumptions. 

Series roadmap 

This post is the second in a series. In Blog 1, we introduced the broader migration path for Elasticsearch users moving to Azure Cosmos DB and outlined the core concepts behind full text search support. In this post, we focused on how Elasticsearch mappings translate to Azure Cosmos DB indexing and search configuration. Next, Blog 3 will cover query translation, showing how to translate an Elasticsearch Search Request into an Azure Cosmos DB query. 

Author

Madeline Egan
Product Manager

Madeline Egan is a Product Manager at Azure Cosmos DB, specializing in query and search. She is passionate about making it easier for developers to build powerful search experiences on their data.

0 comments