{"id":12933,"date":"2026-10-01T00:00:57","date_gmt":"2026-10-01T07:00:57","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cosmosdb\/?p=12933"},"modified":"2026-09-30T06:46:47","modified_gmt":"2026-09-30T13:46:47","slug":"migrating-elasticsearch-mappings-to-azure-cosmos-db","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cosmosdb\/migrating-elasticsearch-mappings-to-azure-cosmos-db\/","title":{"rendered":"Migrating Elasticsearch Mappings to Azure Cosmos DB"},"content":{"rendered":"<p><span data-contrast=\"auto\">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.<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">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\u2019s intent across the indexing policy, full-text policy, vector policy, and computed properties.<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">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\u2019s container-level model.<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<h2 aria-level=\"1\">Mapping translation at a glance<\/h2>\n<table data-tablestyle=\"MsoTable15Grid4Accent1\" data-tablelook=\"1184\" aria-rowcount=\"5\" aria-colcount=\"2\">\n<tbody>\n<tr aria-rowindex=\"1\">\n<td data-celllook=\"4369\"><b><span data-contrast=\"none\">Elasticsearch<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:160}\">\u00a0<\/span><\/td>\n<td data-celllook=\"4369\"><b><span data-contrast=\"none\">Azure Cosmos DB equivalent<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:160}\">\u00a0<\/span><\/td>\n<\/tr>\n<tr aria-rowindex=\"2\">\n<td data-celllook=\"0\">Mapped fields, index, and field types used for exact-match queries, filters, sorting, and aggregations<\/td>\n<td data-celllook=\"0\"><span data-contrast=\"auto\">Indexing policy: included and excluded paths, range indexes, composite indexes, and spatial indexes<\/span><span data-ccp-props=\"{&quot;335559739&quot;:160}\">\u00a0<\/span><\/td>\n<\/tr>\n<tr aria-rowindex=\"3\">\n<td data-celllook=\"0\">Text fields and analyzers<\/td>\n<td data-celllook=\"0\"><span data-contrast=\"auto\">Full-text policy plus a full-text index in the indexing policy<\/span><span data-ccp-props=\"{&quot;335559739&quot;:160}\">\u00a0<\/span><\/td>\n<\/tr>\n<tr aria-rowindex=\"4\">\n<td data-celllook=\"0\">dense_vector fields and vector index options<\/td>\n<td data-celllook=\"0\"><span data-contrast=\"auto\">Container vector policy plus a vector index in the indexing policy<\/span><span data-ccp-props=\"{&quot;335559739&quot;:160}\">\u00a0<\/span><\/td>\n<\/tr>\n<tr aria-rowindex=\"5\">\n<td data-celllook=\"0\">Runtime fields or values materialized for search<\/td>\n<td data-celllook=\"0\"><span data-contrast=\"auto\">Computed properties<\/span><span data-ccp-props=\"{&quot;335559739&quot;:160}\">\u00a0<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span data-contrast=\"auto\">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.<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<h2 aria-level=\"1\">Translate by capability<\/h2>\n<h4 aria-level=\"2\">1. Exact-match, filter, sort, and range behavior<\/h4>\n<table style=\"width: 55.2106%; height: 296px;\" data-tablestyle=\"MsoTable15Grid4Accent1\" data-tablelook=\"1184\" aria-rowcount=\"2\" aria-colcount=\"2\">\n<tbody>\n<tr style=\"height: 24px;\" aria-rowindex=\"1\">\n<td style=\"height: 24px;\" data-celllook=\"4369\"><b><span data-contrast=\"none\">Elasticsearch<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:160}\">\u00a0<\/span><\/td>\n<td style=\"height: 24px;\" data-celllook=\"4369\"><b><span data-contrast=\"none\">Azure Cosmos DB<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:160}\">\u00a0<\/span><\/td>\n<\/tr>\n<tr style=\"height: 272px;\" aria-rowindex=\"2\">\n<td style=\"height: 272px;\" data-celllook=\"0\">\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">\"properties\": {\r\n\u00a0 \"category\": { \"type\": \"keyword\" },\r\n\u00a0 \"price\": { \"type\": \"double\" },\r\n\u00a0 \"description\": { \"type\": \"text\" }\r\n}\u00a0<\/code><\/pre>\n<\/td>\n<td style=\"height: 272px;\" data-celllook=\"0\">\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">\"indexingPolicy\": {\r\n\u00a0 \"includedPaths\": [\r\n\u00a0\u00a0\u00a0 { \"path\": \"\/category\/?\" },\r\n\u00a0\u00a0\u00a0 { \"path\": \"\/price\/?\" }\r\n\u00a0 ],\r\n\u00a0 \"excludedPaths\": [\r\n\u00a0\u00a0\u00a0 { \"path\": \"\/description\/?\" }\r\n\u00a0 ]\r\n}<\/code><\/pre>\n<p><span data-ccp-props=\"{&quot;335557856&quot;:15987699,&quot;335559739&quot;:160}\">\u00a0<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><b><span data-contrast=\"auto\">What changes:<\/span><\/b><span data-contrast=\"auto\"> 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.<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<h4 aria-level=\"2\">2. Full-text fields and analyzers<\/h4>\n<table data-tablestyle=\"MsoTable15Grid4Accent1\" data-tablelook=\"1184\" aria-rowcount=\"2\" aria-colcount=\"2\">\n<tbody>\n<tr aria-rowindex=\"1\">\n<td data-celllook=\"4369\"><b><span data-contrast=\"none\">Elasticsearch<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:160}\">\u00a0<\/span><\/td>\n<td data-celllook=\"4369\"><b><span data-contrast=\"none\">Azure Cosmos DB<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:160}\">\u00a0<\/span><\/td>\n<\/tr>\n<tr aria-rowindex=\"2\">\n<td data-celllook=\"0\">\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">\"properties\": {\r\n\u00a0 \"description\": {\r\n\u00a0\u00a0\u00a0 \"type\": \"text\",\r\n\u00a0\u00a0\u00a0 \"analyzer\": \"english\"\r\n\u00a0 },\r\n\u00a0 \"sku\": { \"type\": \"keyword\" }\r\n}\u00a0<\/code><\/pre>\n<\/td>\n<td data-celllook=\"0\">\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">\"fullTextPolicy\": {\r\n\u00a0 \"defaultLanguage\": \"en-US\",\r\n\u00a0 \"fullTextPaths\": [\r\n\u00a0\u00a0\u00a0 { \"path\": \"\/description\",\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 \"language\": \"en-US\" }\r\n\u00a0 ]\r\n}\r\n\r\n\"fullTextIndexes\": [\r\n\u00a0 { \"path\": \"\/description\" }\r\n]\u00a0<\/code><\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><b><span data-contrast=\"auto\">What changes:<\/span><\/b><span data-contrast=\"auto\"> Translate the analyzer\u2019s intent\u2014language-aware tokenization, stemming, and stop-word handling\u2014rather than copying a custom analysis chain. Keep <\/span><b><span data-contrast=\"auto\">sku<\/span><\/b><span data-contrast=\"auto\"> in the regular indexing policy for exact matches.<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<h4 aria-level=\"2\">3. Vector fields<\/h4>\n<table style=\"width: 41.1723%;\" data-tablestyle=\"MsoTable15Grid4Accent1\" data-tablelook=\"1184\" aria-rowcount=\"2\" aria-colcount=\"2\">\n<tbody>\n<tr aria-rowindex=\"1\">\n<td style=\"width: 48.9083%;\" data-celllook=\"4369\"><b><span data-contrast=\"none\">Elasticsearch<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:160}\">\u00a0<\/span><\/td>\n<td style=\"width: 49.5633%;\" data-celllook=\"4369\"><b><span data-contrast=\"none\">Azure Cosmos DB<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:160}\">\u00a0<\/span><\/td>\n<\/tr>\n<tr aria-rowindex=\"2\">\n<td style=\"width: 48.9083%;\" data-celllook=\"0\">\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">\"content_vector\": {\r\n\u00a0 \"type\": \"dense_vector\",\r\n\u00a0 \"dims\": 384,\r\n\u00a0 \"similarity\": \"cosine\",\r\n\u00a0 \"index\": true\r\n}\u00a0<\/code><\/pre>\n<\/td>\n<td style=\"width: 49.5633%;\" data-celllook=\"0\">\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">\"vectorEmbeddingPolicy\": {\r\n\u00a0 \"vectorEmbeddings\": [{\r\n\u00a0\u00a0\u00a0 \"path\": \"\/contentVector\",\r\n\u00a0\u00a0\u00a0 \"dataType\": \"float32\",\r\n\u00a0\u00a0\u00a0 \"distanceFunction\": \"cosine\",\r\n\u00a0\u00a0\u00a0 \"dimensions\": 384\r\n\u00a0 }]\r\n}\r\n\r\n\"vectorIndexes\": [{\r\n\u00a0 \"path\": \"\/contentVector\",\r\n\u00a0 \"type\": \"quantizedFlat\"\r\n}]<\/code><span data-ccp-props=\"{&quot;335557856&quot;:15987699,&quot;335559739&quot;:160}\">\u00a0<\/span><\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><b><span data-contrast=\"auto\">What changes:<\/span><\/b><span data-contrast=\"auto\"> Preserve the embedding model\u2019s dimensions and similarity function. Select the Azure Cosmos DB vector index type according to data size, filters, latency, and recall.<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<h4 aria-level=\"2\"><b><span data-contrast=\"none\">4. Derived and runtime values<\/span><\/b><span data-ccp-props=\"{&quot;335559738&quot;:180,&quot;335559739&quot;:90}\">\u00a0<\/span><\/h4>\n<table data-tablestyle=\"MsoTable15Grid4Accent1\" data-tablelook=\"1184\" aria-rowcount=\"2\" aria-colcount=\"2\">\n<tbody>\n<tr aria-rowindex=\"1\">\n<td data-celllook=\"4369\"><b><span data-contrast=\"none\">Elasticsearch<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:160}\">\u00a0<\/span><\/td>\n<td data-celllook=\"4369\"><b><span data-contrast=\"none\">Azure Cosmos DB<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:160}\">\u00a0<\/span><\/td>\n<\/tr>\n<tr aria-rowindex=\"2\">\n<td data-celllook=\"0\">\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">\"runtime\": {\r\n\u00a0 \"discountedPrice\": {\r\n\u00a0\u00a0\u00a0 \"type\": \"double\",\r\n\u00a0\u00a0\u00a0 \"script\": {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 \"source\": \"emit(doc['price'].value * 0.9)\"\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0 }\r\n}\u00a0<\/code><\/pre>\n<\/td>\n<td data-celllook=\"0\">\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">\"computedProperties\": [{\r\n\u00a0 \"name\": \"discountedPrice\",\r\n\u00a0 \"query\": \"SELECT VALUE c.price * 0.9 FROM c\"\r\n}]\u00a0<\/code><\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><b><span data-contrast=\"auto\">What changes:<\/span><\/b><span data-contrast=\"auto\"> Rewrite a stable, deterministic derivation as a computed property. Calculate unsupported or external-state logic during ingestion or in the application.<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<h2 aria-level=\"1\"><b><span data-contrast=\"none\">Recommended migration sequence<\/span><\/b><span data-ccp-props=\"{&quot;335559738&quot;:260,&quot;335559739&quot;:120}\">\u00a0<\/span><\/h2>\n<ol>\n<li aria-setsize=\"-1\" data-leveltext=\"%1.\" data-font=\"\" data-listid=\"3\" data-list-defn-props=\"{&quot;335552541&quot;:0,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769242&quot;:[65533,0],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;%1.&quot;,&quot;469777815&quot;:&quot;multilevel&quot;}\" data-aria-posinset=\"1\" data-aria-level=\"1\"><b><span data-contrast=\"auto\">Inventory the mapping and workload.<\/span><\/b><span data-contrast=\"auto\"> Export mappings, templates, analyzers, vector settings, runtime fields, and the queries that use them.<\/span><span data-ccp-props=\"{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:278}\">\u00a0<\/span><\/li>\n<\/ol>\n<ol>\n<li aria-setsize=\"-1\" data-leveltext=\"%1.\" data-font=\"\" data-listid=\"3\" data-list-defn-props=\"{&quot;335552541&quot;:0,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769242&quot;:[65533,0],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;%1.&quot;,&quot;469777815&quot;:&quot;multilevel&quot;}\" data-aria-posinset=\"2\" data-aria-level=\"1\"><b><span data-contrast=\"auto\">Classify every field by behavior.<\/span><\/b><span data-contrast=\"auto\"> Mark paths for exact filtering or sorting, full-text search, vector search, geospatial queries, or derived values.<\/span><span data-ccp-props=\"{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:278}\">\u00a0<\/span><\/li>\n<\/ol>\n<ol>\n<li aria-setsize=\"-1\" data-leveltext=\"%1.\" data-font=\"\" data-listid=\"3\" data-list-defn-props=\"{&quot;335552541&quot;:0,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769242&quot;:[65533,0],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;%1.&quot;,&quot;469777815&quot;:&quot;multilevel&quot;}\" data-aria-posinset=\"3\" data-aria-level=\"1\"><b><span data-contrast=\"auto\">Design the container policies together.<\/span><\/b><span data-contrast=\"auto\"> Resolve overlaps\u2014for example, a description can be available to normal queries, full-text search, and vector retrieval.<\/span><span data-ccp-props=\"{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:278}\">\u00a0<\/span><\/li>\n<\/ol>\n<ol>\n<li aria-setsize=\"-1\" data-leveltext=\"%1.\" data-font=\"\" data-listid=\"3\" data-list-defn-props=\"{&quot;335552541&quot;:0,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769242&quot;:[65533,0],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;%1.&quot;,&quot;469777815&quot;:&quot;multilevel&quot;}\" data-aria-posinset=\"4\" data-aria-level=\"1\"><b><span data-contrast=\"auto\">Validate with representative data and queries.<\/span><\/b><span data-contrast=\"auto\"> Compare result correctness, relevance ordering, latency, RU consumption, and write cost.<\/span><span data-ccp-props=\"{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:278}\">\u00a0<\/span><\/li>\n<\/ol>\n<ol>\n<li aria-setsize=\"-1\" data-leveltext=\"%1.\" data-font=\"\" data-listid=\"3\" data-list-defn-props=\"{&quot;335552541&quot;:0,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769242&quot;:[65533,0],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;%1.&quot;,&quot;469777815&quot;:&quot;multilevel&quot;}\" data-aria-posinset=\"5\" data-aria-level=\"1\"><b><span data-contrast=\"auto\">Roll out deliberately.<\/span><\/b><span data-contrast=\"auto\"> Apply policy changes before dependent queries, monitor index transformation where applicable, and keep a rollback path.<\/span><span data-ccp-props=\"{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:278}\">\u00a0<\/span><\/li>\n<\/ol>\n<h2 aria-level=\"1\"><b><span data-contrast=\"none\">Key takeaway<\/span><\/b><span data-ccp-props=\"{&quot;335559738&quot;:260,&quot;335559739&quot;:120}\">\u00a0<\/span><\/h2>\n<p><span data-contrast=\"auto\">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.<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<h2 aria-level=\"1\"><b><span data-contrast=\"none\">Series roadmap<\/span><\/b><span data-ccp-props=\"{&quot;335559738&quot;:260,&quot;335559739&quot;:120}\">\u00a0<\/span><\/h2>\n<p><span data-contrast=\"none\">This post is the second in a series. In <\/span><b><span data-contrast=\"none\">Blog 1<\/span><\/b><span data-contrast=\"none\">, 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, <\/span><b><span data-contrast=\"none\">Blog 3<\/span><\/b><span data-contrast=\"none\"> will cover query translation, showing how to translate an Elasticsearch Search Request into an Azure Cosmos DB query.<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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.\u00a0 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. [&hellip;]<\/p>\n","protected":false},"author":220740,"featured_media":13015,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[14],"tags":[],"class_list":["post-12933","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-core-sql-api"],"acf":[],"blog_post_summary":"<p>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.\u00a0 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. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/12933","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/users\/220740"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/comments?post=12933"}],"version-history":[{"count":1,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/12933\/revisions"}],"predecessor-version":[{"id":12947,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/12933\/revisions\/12947"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media\/13015"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media?parent=12933"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/categories?post=12933"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/tags?post=12933"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}