{"id":12935,"date":"2026-10-02T00:00:14","date_gmt":"2026-10-02T07:00:14","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cosmosdb\/?p=12935"},"modified":"2026-09-30T06:52:44","modified_gmt":"2026-09-30T13:52:44","slug":"translating-an-elasticsearch-search-request-to-azure-cosmos-db","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cosmosdb\/translating-an-elasticsearch-search-request-to-azure-cosmos-db\/","title":{"rendered":"Translating an Elasticsearch Search Request to Azure Cosmos DB\u00a0"},"content":{"rendered":"<p aria-level=\"1\"><span data-contrast=\"auto\">This tutorial shows how common Elasticsearch search requests can be expressed using Azure Cosmos DB query patterns. Some Elasticsearch capabilities map directly to Cosmos DB full-text search functions, while others require separate queries or application-layer handling. Each step shows the closest Cosmos DB pattern and explains what changes in the process.<\/span><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:360,&quot;335559739&quot;:80}\">\u00a0<\/span><\/p>\n<p aria-level=\"1\"><span data-contrast=\"auto\">In Elasticsearch, one search request can return hits, highlights, and aggregation buckets together. In Azure Cosmos DB, it is clearer to separate those concerns: one query retrieves ranked results, separate aggregate queries calculate facets, and the application handles presentation features such as highlighting.<\/span><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:360,&quot;335559739&quot;:80}\">\u00a0<\/span><\/p>\n<h4 aria-level=\"1\"><span data-contrast=\"none\">Step 1: Translate the ranked result query<\/span><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:360,&quot;335559739&quot;:80}\">\u00a0<\/span><\/h4>\n<p><span data-contrast=\"auto\">Start with an Elasticsearch multi_match query for \u201cshoes\u201d across title, description, brand, and category. The request returns the first 20 hits.<\/span><span data-ccp-props=\"{&quot;335559739&quot;:120}\">\u00a0<\/span><\/p>\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=\"69905\"><b><span data-contrast=\"none\">Elasticsearch<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:80}\">\u00a0<\/span><\/td>\n<td data-celllook=\"69905\"><b><span data-contrast=\"none\">Azure Cosmos DB<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:80}\">\u00a0<\/span><\/td>\n<\/tr>\n<tr aria-rowindex=\"2\">\n<td data-celllook=\"4369\">\n<pre class=\"prettyprint language-sql\"><code class=\"language-sql\">{ \r\n  \"from\": 0, \r\n  \"size\": 20, \r\n  \"query\": { \r\n    \"bool\": { \r\n      \"must\": [{ \r\n        \"multi_match\": { \r\n          \"query\": \"shoes\", \r\n          \"fields\": [\"title^3\", \"description\", \r\n                     \"brand^2\", \"category\"], \r\n          \"type\": \"best_fields\", \r\n          \"fuzziness\": \"AUTO\" \r\n        } \r\n      }] \r\n    } \r\n  } \r\n} <\/code><\/pre>\n<\/td>\n<td data-celllook=\"4369\">\n<pre class=\"prettyprint language-sql\"><code class=\"language-sql\">SELECT *\u00a0\r\nFROM c\u00a0\r\nWHERE (\u00a0\r\n\u00a0 FullTextContains(c.title, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.description, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.brand, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.category, 'shoes')\u00a0\r\n)\u00a0\r\nORDER BY RANK FullTextScore(c.title, ['shoes'])\u00a0\r\nOFFSET 0 LIMIT 20 <\/code><\/pre>\n<p><span data-ccp-props=\"{&quot;335559739&quot;:120}\">\u00a0<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p aria-level=\"1\"><b><span data-contrast=\"auto\">This translation focuses on the core search behavior rather than an exact one-to-one mapping of every Elasticsearch construct. In Elasticsearch, title<sup>3<\/sup> and brand<sup>2<\/sup> are field boosts that make matches in the title and brand fields more influential in relevance scoring. <\/span><\/b><span data-contrast=\"auto\">The Azure Cosmos DB query shown here does not replicate those boost factors because field boosting is not currently supported in Azure Cosmos DB for NoSQL full-text search. Instead, results are ranked using the built-in BM25-based full-text scoring model. As a result, the returned result set and ranking order will differ from Elasticsearch when field boosts contribute to relevance. However, the BM25 scoring model is still designed to surface relevant matches first, so users can expect relevant results even though the ranking behavior is not identical.<\/span><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:360,&quot;335559739&quot;:80}\">\u00a0<\/span><\/p>\n<h4 aria-level=\"1\"><span data-contrast=\"none\">Step 2: Split categorical facets into aggregate queries<\/span><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:360,&quot;335559739&quot;:80}\">\u00a0<\/span><\/h4>\n<p><span data-contrast=\"auto\">The Elasticsearch query returns categories, subcategories, and brands as aggregation buckets in a single request.<\/span><span data-ccp-props=\"{&quot;335559739&quot;:120}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">In Azure Cosmos DB, run one aggregate query for each field. Each query repeats the result query\u2019s text predicate and returns a facet key with a count.<\/span><span data-ccp-props=\"{&quot;335559739&quot;:120}\">\u00a0<\/span><\/p>\n<table style=\"width: 74.5653%;\" data-tablestyle=\"MsoTable15Grid4Accent1\" data-tablelook=\"1184\" aria-rowcount=\"2\" aria-colcount=\"2\">\n<tbody>\n<tr aria-rowindex=\"1\">\n<td style=\"width: 61.3365%;\" data-celllook=\"69905\"><b><span data-contrast=\"none\">Elasticsearch<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:80}\">\u00a0<\/span><\/td>\n<td style=\"width: 37.8282%;\" data-celllook=\"69905\"><b><span data-contrast=\"none\">Azure Cosmos DB<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:80}\">\u00a0<\/span><\/td>\n<\/tr>\n<tr aria-rowindex=\"2\">\n<td style=\"width: 61.3365%;\" data-celllook=\"4369\">\n<pre class=\"prettyprint language-sql\"><code class=\"language-sql\">\"categories\": {\u00a0\r\n\u00a0 \"terms\": { \"field\": \"category.keyword\", \"size\": 20 }\u00a0\r\n},\u00a0\r\n\"subcategories\": {\u00a0\r\n\u00a0 \"terms\": { \"field\": \"subcategory.keyword\", \"size\": 30 }\u00a0\r\n},\u00a0\r\n\"brands\": {\u00a0\r\n\u00a0 \"terms\": { \"field\": \"brand.keyword\", \"size\": 30 }\u00a0\r\n}\u00a0<\/code><\/pre>\n<p><span data-ccp-props=\"{&quot;335559739&quot;:120}\">\u00a0<\/span><\/td>\n<td style=\"width: 37.8282%;\" data-celllook=\"4369\">\n<h5 aria-level=\"2\"><span data-contrast=\"none\">Category<\/span><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:160,&quot;335559739&quot;:80}\">\u00a0<\/span><\/h5>\n<pre class=\"prettyprint language-sql\"><code class=\"language-sql\">SELECT\u00a0\r\n\u00a0 c.category AS facetKey,\u00a0\r\n\u00a0 COUNT(1) AS facetCount\u00a0\r\nFROM c\u00a0\r\nWHERE (\u00a0\r\n\u00a0 FullTextContains(c.title, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.description, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.brand, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.category, 'shoes')\u00a0\r\n)\u00a0\r\nGROUP BY c.category\u00a0<\/code><\/pre>\n<h5 aria-level=\"2\"><span data-contrast=\"none\">Subcategory<\/span><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:160,&quot;335559739&quot;:80}\">\u00a0<\/span><\/h5>\n<pre class=\"prettyprint language-sql\"><code class=\"language-sql\">SELECT\u00a0\r\n\u00a0 c.subcategory AS facetKey,\u00a0\r\n\u00a0 COUNT(1) AS facetCount\u00a0\r\nFROM c\u00a0\r\nWHERE (\u00a0\r\n\u00a0 FullTextContains(c.title, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.description, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.brand, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.category, 'shoes')\u00a0\r\n)\u00a0\r\nGROUP BY c.subcategory\u00a0<\/code><\/pre>\n<h5 aria-level=\"2\"><span data-contrast=\"none\">Brand<\/span><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:160,&quot;335559739&quot;:80}\">\u00a0<\/span><\/h5>\n<pre class=\"prettyprint language-sql\"><code class=\"language-sql\">SELECT\u00a0\r\n\u00a0 c.brand AS facetKey,\u00a0\r\n\u00a0 COUNT(1) AS facetCount\u00a0\r\nFROM c\u00a0\r\nWHERE (\u00a0\r\n\u00a0 FullTextContains(c.title, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.description, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.brand, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.category, 'shoes')\u00a0\r\n)\u00a0\r\nGROUP BY c.brand\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\"> Instead of receiving all buckets in the result response, the application issues focused aggregate queries and combines the counts with the result list.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:80,&quot;335559739&quot;:200}\">\u00a0<\/span><\/p>\n<h4 aria-level=\"1\"><span data-contrast=\"none\">Step 3: Translate derived rating buckets<\/span><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:360,&quot;335559739&quot;:80}\">\u00a0<\/span><\/h4>\n<p><span data-contrast=\"auto\">The Elasticsearch query creates rating facets by converting each rating to its floor value before grouping.<\/span><span data-ccp-props=\"{&quot;335559739&quot;:120}\">\u00a0<\/span><\/p>\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=\"69905\"><b><span data-contrast=\"none\">Elasticsearch<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:80}\">\u00a0<\/span><\/td>\n<td data-celllook=\"69905\"><b><span data-contrast=\"none\">Azure Cosmos DB<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:80}\">\u00a0<\/span><\/td>\n<\/tr>\n<tr aria-rowindex=\"2\">\n<td data-celllook=\"4369\">\n<pre class=\"prettyprint language-default\"><code class=\"language-default\">\"ratings\": {\u00a0\r\n\u00a0 \"terms\": {\u00a0\r\n\u00a0\u00a0\u00a0 \"script\": \"Math.floor(doc['rating'].value)\",\u00a0\r\n\u00a0\u00a0\u00a0 \"size\": 5\u00a0\r\n\u00a0 }\u00a0\r\n}\u00a0<\/code><\/pre>\n<\/td>\n<td data-celllook=\"4369\">\n<pre class=\"prettyprint language-sql\"><code class=\"language-sql\">SELECT\u00a0\r\n\u00a0 FLOOR(c.rating) AS facetKey,\u00a0\r\n\u00a0 COUNT(1) AS facetCount\u00a0\r\nFROM c\u00a0\r\nWHERE (\u00a0\r\n\u00a0 FullTextContains(c.title, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.description, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.brand, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.category, 'shoes')\u00a0\r\n)\u00a0\r\nGROUP BY FLOOR(c.rating)\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\">: In Elasticsearch, the bucket value is produced by a script inside the aggregation. In Azure Cosmos DB, the derived bucket value is expressed directly in SQL using FLOOR(c.rating) and then used in both SELECT and GROUP BY. The result is the same type of facet output: one row per rating bucket, with a count of matching documents in each bucket.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:80,&quot;335559739&quot;:200}\">\u00a0<\/span><\/p>\n<h4 aria-level=\"1\"><span data-contrast=\"none\">Step 4: Translate price range facets<\/span><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:360,&quot;335559739&quot;:80}\">\u00a0<\/span><\/h4>\n<p><span data-contrast=\"auto\">The Elasticsearch query creates fixed price ranges and returns a count for each bucket. In Azure Cosmos DB, the same result can be produced with conditional aggregate expressions: each SUM counts documents that fall into one price range.<\/span><span data-ccp-props=\"{&quot;335559739&quot;:120}\">\u00a0<\/span><\/p>\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=\"69905\"><b><span data-contrast=\"none\">Elasticsearch<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:80}\">\u00a0<\/span><\/td>\n<td data-celllook=\"69905\"><b><span data-contrast=\"none\">Azure Cosmos DB<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:80}\">\u00a0<\/span><\/td>\n<\/tr>\n<tr aria-rowindex=\"2\">\n<td data-celllook=\"4369\">\n<pre class=\"prettyprint language-sql\"><code class=\"language-sql\">\"price_ranges\": {\u00a0\r\n\u00a0 \"range\": {\u00a0\r\n\u00a0\u00a0\u00a0 \"field\": \"price\",\u00a0\r\n\u00a0\u00a0\u00a0 \"ranges\": [\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 { \"key\": \"Under $25\", \"to\": 25 },\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 { \"key\": \"$25 - $50\", \"from\": 25, \"to\": 50 },\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 { \"key\": \"$50 - $100\", \"from\": 50, \"to\": 100 },\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 { \"key\": \"$100 - $200\", \"from\": 100, \"to\": 200 },\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 { \"key\": \"$200 - $500\", \"from\": 200, \"to\": 500 },\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 { \"key\": \"$500+\", \"from\": 500 }\u00a0\r\n\u00a0\u00a0\u00a0 ]\u00a0\r\n\u00a0 }\u00a0\r\n}\u00a0<\/code><\/pre>\n<\/td>\n<td data-celllook=\"4369\">\n<pre class=\"prettyprint language-sql\"><code class=\"language-sql\">SELECT\u00a0\r\n\u00a0 SUM(c.price &lt; 25 ? 1 : 0) AS under25,\u00a0\r\n\u00a0 SUM(c.price &gt;= 25 AND c.price &lt; 50 ? 1 : 0) AS r25to50,\u00a0\r\n\u00a0 SUM(c.price &gt;= 50 AND c.price &lt; 100 ? 1 : 0) AS r50to100,\u00a0\r\n\u00a0 SUM(c.price &gt;= 100 AND c.price &lt; 200 ? 1 : 0) AS r100to200,\u00a0\r\n\u00a0 SUM(c.price &gt;= 200 AND c.price &lt; 500 ? 1 : 0) AS r200to500,\u00a0\r\n\u00a0 SUM(c.price &gt;= 500 ? 1 : 0) AS over500\u00a0\r\nFROM c\u00a0\r\nWHERE (\u00a0\r\n\u00a0 FullTextContains(c.title, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.description, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.brand, 'shoes')\u00a0\r\n\u00a0 OR FullTextContains(c.category, 'shoes')\u00a0\r\n)\u00a0<\/code><span data-ccp-props=\"{&quot;335559739&quot;:120}\">\u00a0<\/span><\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p aria-level=\"1\"><span data-contrast=\"auto\"><strong>What changes<\/strong>:<\/span> Elasticsearch represents price ranges as a dedicated range aggregation. In Azure Cosmos DB, each range is written as a conditional count in the SELECT clause. The query still uses the same full-text predicate as the result query, so the price buckets count only documents that match the current search. This keeps the facet counts aligned with the result list.<\/p>\n<p aria-level=\"1\">Price boundaries can vary by what a user searches for, so precomputing them is rarely the default solution. You can also group by a derived key such as FLOOR(c.rating). More information about faceting can be found <a href=\"https:\/\/learn.microsoft.com\/azure\/cosmos-db\/gen-ai\/full-text-search#faceting\">here<\/a>.<\/p>\n<h4 aria-level=\"1\"><span data-contrast=\"none\">Step 5: Handle highlighting in the application<\/span><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:360,&quot;335559739&quot;:80}\">\u00a0<\/span><\/h4>\n<p><span data-contrast=\"auto\">The Elasticsearch request configures highlighted fragments and mark tags for title and description.<\/span><span data-ccp-props=\"{&quot;335559739&quot;:120}\">\u00a0<\/span><\/p>\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=\"69905\"><b><span data-contrast=\"none\">Elasticsearch<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:80}\">\u00a0<\/span><\/td>\n<td data-celllook=\"69905\"><b><span data-contrast=\"none\">Azure Cosmos DB<\/span><\/b><span data-ccp-props=\"{&quot;335559739&quot;:80}\">\u00a0<\/span><\/td>\n<\/tr>\n<tr aria-rowindex=\"2\">\n<td data-celllook=\"69905\">\n<pre class=\"prettyprint language-sql\"><code class=\"language-sql\">\"highlight\": {\u00a0\r\n\u00a0 \"pre_tags\": [\"&lt;mark&gt;\"],\u00a0\r\n\u00a0 \"post_tags\": [\"&lt;\/mark&gt;\"],\u00a0\r\n\u00a0 \"fields\": {\u00a0\r\n\u00a0\u00a0\u00a0 \"title\": { \"number_of_fragments\": 1, \"fragment_size\": 200 },\u00a0\r\n\u00a0\u00a0\u00a0 \"description\": { \"number_of_fragments\": 2, \"fragment_size\": 150 }\u00a0\r\n\u00a0 }\u00a0\r\n}\u00a0<\/code><\/pre>\n<\/td>\n<td data-celllook=\"69905\"><span data-contrast=\"none\">Azure Cosmos DB does not return highlighted fragments as part of the full-text query response. To recreate this behavior, run the search query normally, then generate snippets in the application layer by locating the matched query terms in fields such as title and description and wrapping them with display markup like &lt;mark&gt;&#8230;&lt;\/mark&gt;.<\/span><span data-ccp-props=\"{&quot;335559739&quot;:120}\">\u00a0<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span data-contrast=\"auto\">Native hit highlighting is currently under development.<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<h4 aria-level=\"1\"><span data-contrast=\"none\">Run the translated search<\/span><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:360,&quot;335559739&quot;:80}\">\u00a0<\/span><\/h4>\n<ol>\n<li><b><span data-contrast=\"auto\"> Execute the result query.<\/span><\/b><span data-contrast=\"auto\"> Use the ranked query to retrieve the current page of matching documents.<\/span><\/li>\n<li><b><span data-contrast=\"auto\"> Execute the required facet queries.<\/span><\/b><span data-contrast=\"auto\"> Run category, subcategory, brand, rating, and price aggregates for the same search state.<\/span><\/li>\n<li><b><span data-contrast=\"auto\"> Apply active filters everywhere.<\/span><\/b><span data-contrast=\"auto\"> When a user narrows the search, add that filter to the result query and to every aggregate query before refreshing the UI.<\/span><\/li>\n<li><b><span data-contrast=\"auto\"> Render the experience.<\/span><\/b><span data-contrast=\"auto\"> Display results, counts, and client-side highlights together so navigation reflects a consistent result set.<\/span><\/li>\n<\/ol>\n<h4 aria-level=\"1\"><span data-contrast=\"none\">Validate behavior, not just syntax<\/span><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:360,&quot;335559739&quot;:80}\">\u00a0<\/span><\/h4>\n<p><span data-contrast=\"auto\">Start with a representative set of search terms and documents, then repeat the validation with production-like data. Compare ranked results, selected filters, facet counts, page behavior, request units, and end-to-end latency. This turns the tutorial from a syntax exercise into application-level validation.<\/span><span data-ccp-props=\"{&quot;335559739&quot;:120}\">\u00a0<\/span><\/p>\n<h2 aria-level=\"1\"><span data-contrast=\"none\">Series roadmap<\/span><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:360,&quot;335559739&quot;:80}\">\u00a0<\/span><\/h2>\n<p><span data-contrast=\"auto\">This post is the third and final post in the series. In <\/span><b><span data-contrast=\"auto\">Blog 1<\/span><\/b><span data-contrast=\"auto\">, we introduced the overall migration path for Elasticsearch users moving to Azure Cosmos DB. In <\/span><b><span data-contrast=\"auto\">Blog 2<\/span><\/b><span data-contrast=\"auto\">, we looked at how Elasticsearch mappings can be translated into Azure Cosmos DB indexing and full text search configuration. In this post, we brought those concepts together by walking through how to translate an Elasticsearch Search Request into an Azure Cosmos DB query.<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">With these three posts, you now have a starting framework for evaluating and migrating Elasticsearch-backed search workloads to Azure Cosmos DB: understand the feature model, map your indexing configuration, and translate your query patterns. For more guidance, review the Azure Cosmos DB full text search documentation or reach out to the Azure Cosmos DB team for help with your migration scenario.<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<p><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how common Elasticsearch search requests can be expressed using Azure Cosmos DB query patterns. Some Elasticsearch capabilities map directly to Cosmos DB full-text search functions, while others require separate queries or application-layer handling. Each step shows the closest Cosmos DB pattern and explains what changes in the process.\u00a0 In Elasticsearch, one search [&hellip;]<\/p>\n","protected":false},"author":220740,"featured_media":13017,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[14],"tags":[],"class_list":["post-12935","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-core-sql-api"],"acf":[],"blog_post_summary":"<p>This tutorial shows how common Elasticsearch search requests can be expressed using Azure Cosmos DB query patterns. Some Elasticsearch capabilities map directly to Cosmos DB full-text search functions, while others require separate queries or application-layer handling. Each step shows the closest Cosmos DB pattern and explains what changes in the process.\u00a0 In Elasticsearch, one search [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/12935","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=12935"}],"version-history":[{"count":1,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/12935\/revisions"}],"predecessor-version":[{"id":12949,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/12935\/revisions\/12949"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media\/13017"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media?parent=12935"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/categories?post=12935"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/tags?post=12935"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}