{"id":3337,"date":"2021-09-09T12:30:10","date_gmt":"2021-09-09T19:30:10","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cosmosdb\/?p=3337"},"modified":"2021-09-29T14:47:04","modified_gmt":"2021-09-29T21:47:04","slug":"getting-started-end-to-end-example-1","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cosmosdb\/getting-started-end-to-end-example-1\/","title":{"rendered":"Getting started with Azure Cosmos DB &#8211; end to end example"},"content":{"rendered":"<p>This is the first of two articles in which we will walk you through the steps for realizing your first Azure Cosmos DB implementation.\u00a0In this post, we cover:<\/p>\n<ul>\n<li>Relational or NoSQL<\/li>\n<li>Identify access patterns<\/li>\n<li>Configure Azure Cosmos DB<\/li>\n<li>Using the Client SDK<\/li>\n<\/ul>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/getting-started-end-to-end-example-2\/\" target=\"_blank\" rel=\"noopener\">Part 2<\/a> looks at performance tuning and monitoring.<\/p>\n<h2><span style=\"font-size: 18pt;\">Relational or NoSQL<\/span><\/h2>\n<p>For our scenario, we need to store data from sports events (e.g., marathon, triathlon, cycling, etc.). Users should be able to select an event and view a leaderboard. The amount of data that will be stored is estimated at 100 GB.<\/p>\n<p>The schema of the data is different for various events and likely to change. As a result, this requires the database to be schema-agnostic and therefore we decided to use Azure Cosmos DB as our database. For more information, see <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/relational-nosql\" target=\"_blank\" rel=\"noopener\">Understanding the differences between Azure Cosmos DB NoSQL and relational databases | Microsoft Docs<\/a>.<\/p>\n<h2><span style=\"font-size: 18pt;\">Identify access patterns<\/span><\/h2>\n<p>To design an efficient data model it is important to understand how the client application will interact with Azure Cosmos DB. The most important questions are:<\/p>\n<ol>\n<li>Is the access pattern more read-heavy or write-heavy?<\/li>\n<li>What are the main queries?<\/li>\n<li>What is the expected document size?<\/li>\n<\/ol>\n<p>If the access pattern is read-heavy you want to choose a partition key that appears frequently as a filter in your queries. Queries can be efficiently routed to only the relevant physical partitions by including the partition key in the filter predicate.<\/p>\n<p>When the access pattern is write-heavy you might want to choose item ID as the partition key. Item ID does a great job with evenly balancing partitioned throughput (RUs) and data storage since it\u2019s a unique value. For more information, see <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/partitioning-overview#using-item-id-as-the-partition-key\" target=\"_blank\" rel=\"noopener\">Partitioning and horizontal scaling in Azure Cosmos DB | Microsoft Docs<\/a>.<\/p>\n<p>Finally, we need to understand the document size. 1 kb documents are very efficient in Azure Cosmos DB. To understand the impact of large documents on RU utilization see the <a href=\"https:\/\/cosmos.azure.com\/capacitycalculator\/\" target=\"_blank\" rel=\"noopener\">capacity calculator<\/a> and change the item size to a larger value.\u00a0As a starting point you should start with only one container and embed all values of an entity in a single JSON document. This provides the best reading performance. However, if your document size is unpredictable and can grow to hundreds of kilobytes you might want to split these in different documents within the same container.\u00a0For more information, see <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/modeling-data\" target=\"_blank\" rel=\"noopener\">Modeling data in Azure Cosmos DB &#8211; Azure Cosmos DB | Microsoft Docs<\/a>.<\/p>\n<p>Let\u2019s apply the considerations mentioned above to our scenario:<\/p>\n<h3>Our scenario<\/h3>\n<p>For our scenario, we expect far more reads than writes. Therefore we will optimize our Azure Cosmos DB instance for read access. The main queries for our scenario are:<\/p>\n<h5><strong>Query 1: View top ranked participants for a selected event<\/strong><\/h5>\n<pre class=\"prettyprint\">SELECT * FROM c\u00a0\r\nWHERE c.Eventname = '&lt;eventname&gt;'\r\nAND c.Eventdate = '&lt;eventdate'\r\nORDER BY c.TotalScore asc<\/pre>\n<h5><strong>Query 2: View all events for a selected year a person has participated in<\/strong><\/h5>\n<pre class=\"prettyprint\">SELECT\u00a0c.Eventname\u00a0FROM\u00a0c\u00a0\r\nWHERE c.Eventdate\u00a0&gt;\u00a0'&lt;startdate&gt;'\u00a0AND c.Eventdate\u00a0&lt;\u00a0'&lt;enddate&gt;'\r\nAND c.ParticipantId\u00a0=\u00a0&lt;id&gt;<\/pre>\n<h5><strong>Query 3: View all registered participants per event<\/strong><\/h5>\n<pre class=\"prettyprint\">SELECT\u00a0c.ParticipantFirstname,\u00a0c.ParticipantLastname,\u00a0c.ParticipantId\u00a0\u00a0FROM\u00a0c\u00a0\r\nWHERE c.Eventname\u00a0=\u00a0'&lt;eventname&gt;'<\/pre>\n<h5><strong>Query 4: View total score for a single participant per event<\/strong><\/h5>\n<pre class=\"prettyprint\">SELECT\u00a0c.ParticipantFirstname,\u00a0c.ParticipantLastname,\u00a0c.TotalScore\u00a0FROM\u00a0c\u00a0\r\nWHERE c.ParticipantId\u00a0=\u00a0&lt;id&gt;\r\nAND c.Eventname\u00a0=\u00a0'&lt;eventname&gt;'<\/pre>\n<p>Except for query 2, all these queries are using <em>Eventname <\/em>as a filter. The amount of data stored per event is expected to be 1 GB which is well below the <a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/cosmos-db\/concepts-limits#provisioned-throughput\">20 GB limit<\/a> of a logical partition. Therefore <em>Eventname<\/em> is a great fit as partition key. The document size for our sports events is small; less than 1 kb. Below is an example of such a document. Depending on the event the columns might change.<\/p>\n<pre class=\"prettyprint\">\"id\": \"d5c137ae-5954-4eb2-9a7b-59ad3e65236d\",\r\n\"Eventname\": \"Triathlon Amsterdam\",\r\n\"Eventdate\": \"2021-03-04\",\r\n\"ParticipantId\": 4713,\r\n\"ParticipantLastname\": \"Visser\",\r\n\"ParticipantFirstname\": \"Cyrille\",\r\n\"Category\": \"Olympic\",\r\n\"SwimmingScore\": \"03:17:16\",\r\n\"CyclingScore\": \"03:25:48\",\r\n\"RunningScore\": \"03:04:23\",\r\n\"TotalScore\": \"09:47:27\"<\/pre>\n<h2><span style=\"font-size: 18pt;\">Configure Azure Cosmos DB<\/span><\/h2>\n<p>Now that we have a good understanding of the data model, we can create our Azure Cosmos DB account. For more information, see <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/create-cosmosdb-resources-portal\" target=\"_blank\" rel=\"noopener\">Create an Azure Cosmos account, database, and container from the Azure portal. <\/a>O<span style=\"font-size: 1rem;\">nce the account is created a new database can be created using the Data Explorer:<\/span><\/p>\n<p><img decoding=\"async\" class=\"wp-image-3338\" src=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/application-description-automatically-generated-w.png\" alt=\"Application Description automatically generated with medium confidence\" width=\"409\" height=\"155\" srcset=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/application-description-automatically-generated-w.png 944w, https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/application-description-automatically-generated-w-300x114.png 300w, https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/application-description-automatically-generated-w-768x291.png 768w\" sizes=\"(max-width: 409px) 100vw, 409px\" \/><\/p>\n<p>We will not provision throughput on the database level. Provisioning throughput on the database level is useful when you need multiple containers which have a different utilization pattern. Since we only use a single container and we want predictable throughput for our container, we will provision throughput on the container level. For more information, see <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/set-throughput#set-throughput-on-a-database\" target=\"_blank\" rel=\"noopener\">Provision throughput on Azure Cosmos containers and databases<\/a><\/p>\n<p>Once the database is created a new container can be created:<\/p>\n<p><img decoding=\"async\" class=\"wp-image-3339\" src=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-text-application-email.png\" alt=\"Graphical user interface, text, application, email Description automatically generated\" width=\"303\" height=\"490\" srcset=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-text-application-email.png 818w, https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-text-application-email-185x300.png 185w, https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-text-application-email-633x1024.png 633w, https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-text-application-email-768x1242.png 768w\" sizes=\"(max-width: 303px) 100vw, 303px\" \/><\/p>\n<p>At the container level the partition key is specified, which in our case is \/Eventname. We also provision throughput manually and select 1000 RU as a starting point. You can always change the amount of RU provisioned, or switch to autoscale at any moment in time. This doesn\u2019t cause any downtime. For more information, see <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/how-to-choose-offer\" target=\"_blank\" rel=\"noopener\">How to choose between manual and autoscale on Azure Cosmos DB<\/a>.<\/p>\n<p>Once the container is created, we can add a few documents by selecting items and clicking new item.<\/p>\n<p><img decoding=\"async\" class=\"wp-image-3340\" src=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-application-description.png\" alt=\"Graphical user interface, application Description automatically generated\" width=\"949\" height=\"253\" srcset=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-application-description.png 1781w, https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-application-description-300x80.png 300w, https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-application-description-1024x273.png 1024w, https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-application-description-768x205.png 768w, https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-application-description-1536x410.png 1536w\" sizes=\"(max-width: 949px) 100vw, 949px\" \/><\/p>\n<p>Now we have added a few documents, we click the Query button and test one of our main queries. When clicking on Query Stats we see useful information about the RU consumption and the efficiency of our query. When writing queries for Azure Cosmos DB always validate how efficient your queries are.\u00a0 For more information, see <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/troubleshoot-query-performance\" target=\"_blank\" rel=\"noopener\">Troubleshoot query issues when using Azure Cosmos DB<\/a><\/p>\n<p><img decoding=\"async\" class=\"wp-image-3341\" src=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-text-application-descr.png\" alt=\"Graphical user interface, text, application Description automatically generated\" width=\"800\" height=\"599\" srcset=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-text-application-descr.png 1617w, https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-text-application-descr-300x225.png 300w, https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-text-application-descr-1024x768.png 1024w, https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-text-application-descr-768x576.png 768w, https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2021\/08\/graphical-user-interface-text-application-descr-1536x1151.png 1536w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/p>\n<h2><span style=\"font-size: 18pt;\">Using the Client SDK<\/span><\/h2>\n<p>Now our data model is defined and our Azure Cosmos DB instance is configured we will create the first version of our application using the Client SDK. The Client SDK is available for multiple languages, but for our scenario we will choose the latest stable .NET client library. For more information, see <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/create-sql-api-dotnet\" target=\"_blank\" rel=\"noopener\">Quickstart &#8211; Build a .NET console app to manage Azure Cosmos DB SQL API resources<\/a><\/p>\n<p>It is highly recommended to use a singleton Azure Cosmos DB client for the lifetime of your application. The reason for this is that initiating the client object is an expensive operation. Once initialized the client object addresses connection management and caching. For more information, see <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/performance-tips-dotnet-sdk-v3-sql\" target=\"_blank\" rel=\"noopener\">Azure Cosmos DB performance tips for .NET SDK v3<\/a><\/p>\n<h2><span style=\"font-size: 18pt;\">Writing data<\/span><\/h2>\n<p>Adding an item using the Client SDK is straightforward:<\/p>\n<pre class=\"prettyprint\">ItemResponse&lt;dynamic&gt; response = await _container.CreateItemAsync&lt;dynamic&gt;(item, new PartitionKey(partitionKeyValue));<\/pre>\n<p>The <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/microsoft.azure.cosmos.itemresponse-1?view=azure-dotnet\" target=\"_blank\" rel=\"noopener\">ItemResponse object<\/a> has a property called RequestCharge. This property displays the RU\u2019s being used to perform the insert operation. It is recommended to log this value for troubleshooting purposes. For more information, see <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/find-request-unit-charge?tabs=dotnetv3#use-the-net-sdk\" target=\"_blank\" rel=\"noopener\">Find request unit (RU) charge for a SQL query in Azure Cosmos DB<\/a><\/p>\n<p>In our case the Insert operation consumes <strong>9 RU<\/strong>.<\/p>\n<h2><span style=\"font-size: 18pt;\">Selecting data<\/span><\/h2>\n<p>To prepare and parameterize a query we will use the <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/microsoft.azure.cosmos.querydefinition?view=azure-dotnet\" target=\"_blank\" rel=\"noopener\">QueryDefinition<\/a> object. For creating a query we can use the <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/microsoft.azure.cosmos.container.GetItemQueryIterator\" target=\"_blank\" rel=\"noopener\">GetQueryItemIterator<\/a> method:<\/p>\n<pre class=\"prettyprint\">            List&lt;dynamic&gt; list = new List&lt;dynamic&gt;();\r\n\r\n            QueryDefinition query = new QueryDefinition(\"SELECT c.TotalScore FROM c WHERE c.Eventname = @Eventname AND c.Eventdate = @Eventdate ORDER BY c.TotalScore ASC\")\r\n                .WithParameter(\"@Eventname\", eventName)\r\n                .WithParameter(\"@Eventdate\", eventDate);\r\n\r\n            using (FeedIterator&lt;dynamic&gt; resultset = _container.GetItemQueryIterator&lt;dynamic&gt;(query))\r\n            {\r\n                while (resultset.HasMoreResults)\r\n                {\r\n                    FeedResponse&lt;dynamic&gt; response = await resultset.ReadNextAsync();\r\n                    Console.WriteLine(\"Q1 took {0} ms. RU consumed: {1}, Number of items : {2}\", response.Diagnostics.GetClientElapsedTime().TotalMilliseconds, response.RequestCharge, response.Count);\r\n\r\n                    foreach (var item in response)\r\n                    {\r\n                        list.Add(item);\r\n                    }\r\n                }\r\n            }<\/pre>\n<p>The GetQueryItemIterator returns a <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/microsoft.azure.cosmos.feediterator-1?view=azure-dotnet\" target=\"_blank\" rel=\"noopener\">FeedIterator<\/a> object. With this object, we can loop through the items. You will notice that the SDK applies query pagination. By default, a maximum of 1000 items are returned at once. This can be changed by adjusting the MaxItemCount of the <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/microsoft.azure.cosmos.queryrequestoptions\" target=\"_blank\" rel=\"noopener\">QueryRequestOptions<\/a> object. Using the method <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/microsoft.azure.cosmos.feediterator-1?view=azure-dotnet\" target=\"_blank\" rel=\"noopener\">ReadNextAsync()<\/a> method we can iterate through the entire result set. It is important to understand each iteration consumes RUs.<\/p>\n<p>The table below shows the RUs consumed for each query.<\/p>\n<table style=\"width: 19.1055%;\">\n<tbody>\n<tr>\n<td style=\"width: 13.5447%;\"><strong>Query<\/strong><\/td>\n<td style=\"width: 26.475%;\"><strong># Iterations<\/strong><\/td>\n<td style=\"width: 27.6838%;\"><strong>Items returned<\/strong><\/td>\n<td style=\"width: 42.8709%;\"><strong>RU consumption<\/strong><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 13.5447%;\">1<\/td>\n<td style=\"width: 26.475%;\">6<\/td>\n<td style=\"width: 27.6838%;\">5001<\/td>\n<td style=\"width: 42.8709%;\">208<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 13.5447%;\">2<\/td>\n<td style=\"width: 26.475%;\">1<\/td>\n<td style=\"width: 27.6838%;\">10<\/td>\n<td style=\"width: 42.8709%;\">3<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 13.5447%;\">3<\/td>\n<td style=\"width: 26.475%;\">6<\/td>\n<td style=\"width: 27.6838%;\">5002<\/td>\n<td style=\"width: 42.8709%;\">191<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 13.5447%;\">4<\/td>\n<td style=\"width: 26.475%;\">1<\/td>\n<td style=\"width: 27.6838%;\">1<\/td>\n<td style=\"width: 42.8709%;\">3<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p>In<a href=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/getting-started-end-to-end-example-2\/\" target=\"_blank\" rel=\"noopener\"> part 2<\/a>, we will focus on optimizing our queries.<\/p>\n<p>&nbsp;<\/p>\n<h3>Get started<\/h3>\n<ul>\n<li>Find out more about <a href=\"https:\/\/azure.microsoft.com\/services\/cosmos-db\/\" target=\"_blank\" rel=\"noopener\">Azure Cosmos DB and get started free<\/a><\/li>\n<li>Four ways to <a href=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/four-ways-to-try-azure-cosmos-db-free\/\" target=\"_blank\" rel=\"noopener\">dev\/test free with Azure Cosmos DB<\/a><\/li>\n<li>Find the code used in this example <a href=\"https:\/\/github.com\/cyrille-visser\/cosmosdb\" target=\"_blank\" rel=\"noopener\">on GitHub<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Understand how to create your first Azure Cosmos DB implementation with this two-part series.  From when and why to choose a NoSQL database to creating containers and selecting an API, follow this end-to-end example to walk through the steps you&#8217;ll take to get started.<\/p>\n","protected":false},"author":68471,"featured_media":61,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[14,1611],"tags":[],"class_list":["post-3337","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-core-sql-api","category-data-architecture"],"acf":[],"blog_post_summary":"<p>Understand how to create your first Azure Cosmos DB implementation with this two-part series.  From when and why to choose a NoSQL database to creating containers and selecting an API, follow this end-to-end example to walk through the steps you&#8217;ll take to get started.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/3337","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\/68471"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/comments?post=3337"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/3337\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media\/61"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media?parent=3337"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/categories?post=3337"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/tags?post=3337"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}